(function () {
  UEDITOR_CONFIG = window.UEDITOR_CONFIG || {};
  var baidu = window.baidu || {};
  window.baidu = baidu;
  window.UE = baidu.editor = {
    plugins: {},
    commands: {},
    instants: {},
    I18N: {},
    _customizeUI: {},
    version: '4.4.0',
    plus: {
      fileExt: function (filename) {
        if (!filename) {
          return '';
        }
        var pcs = filename.split('.');
        if (pcs.length > 1) {
          return pcs.pop().toLowerCase();
        }
        return '';
      },
    },
    constants: { STATEFUL: { DISABLED: -1, OFF: 0, ON: 1 } },
  };
  var dom = (UE.dom = {});
  var browser = (UE.browser = (function () {
    var agent = navigator.userAgent.toLowerCase(),
      opera = window.opera,
      browser = {
        ie: /(msie\s|trident.*rv:)([\w.]+)/i.test(agent),
        opera: !!opera && opera.version,
        webkit: agent.indexOf(' applewebkit/') > -1,
        mac: agent.indexOf('macintosh') > -1,
        quirks: document.compatMode == 'BackCompat',
      };
    browser.gecko = navigator.product == 'Gecko' && !browser.webkit && !browser.opera && !browser.ie;
    var version = 0;
    if (browser.ie) {
      var v1 = agent.match(/(?:msie\s([\w.]+))/);
      var v2 = agent.match(/(?:trident.*rv:([\w.]+))/);
      if (v1 && v2 && v1[1] && v2[1]) {
        version = Math.max(v1[1] * 1, v2[1] * 1);
      } else if (v1 && v1[1]) {
        version = v1[1] * 1;
      } else if (v2 && v2[1]) {
        version = v2[1] * 1;
      } else {
        version = 0;
      }
      browser.ie11Compat = document.documentMode == 11;
      browser.ie9Compat = document.documentMode == 9;
      browser.ie8 = !!document.documentMode;
      browser.ie8Compat = document.documentMode == 8;
      browser.ie7Compat = (version == 7 && !document.documentMode) || document.documentMode == 7;
      browser.ie6Compat = version < 7 || browser.quirks;
      browser.ie9above = version > 8;
      browser.ie9below = version < 9;
      browser.ie11above = version > 10;
      browser.ie11below = version < 11;
    }
    if (browser.gecko) {
      var geckoRelease = agent.match(/rv:([\d\.]+)/);
      if (geckoRelease) {
        geckoRelease = geckoRelease[1].split('.');
        version = geckoRelease[0] * 1e4 + (geckoRelease[1] || 0) * 100 + (geckoRelease[2] || 0) * 1;
      }
    }
    if (/chrome\/(\d+\.\d)/i.test(agent)) {
      browser.chrome = +RegExp['$1'];
    }
    if (/(\d+\.\d)?(?:\.\d)?\s+safari\/?(\d+\.\d+)?/i.test(agent) && !/chrome/i.test(agent)) {
      browser.safari = +(RegExp['$1'] || RegExp['$2']);
    }
    if (browser.opera) version = parseFloat(opera.version());
    if (browser.webkit) version = parseFloat(agent.match(/ applewebkit\/(\d+)/)[1]);
    browser.version = version;
    browser.isCompatible =
      !browser.mobile &&
      ((browser.ie && version >= 6) ||
        (browser.gecko && version >= 10801) ||
        (browser.opera && version >= 9.5) ||
        (browser.air && version >= 1) ||
        (browser.webkit && version >= 522) ||
        false);
    return browser;
  })());
  var ie = browser.ie,
    webkit = browser.webkit,
    gecko = browser.gecko,
    opera = browser.opera;
  var utils = (UE.utils = {
    each: function (obj, iterator, context) {
      if (obj == null) return;
      if (obj.length === +obj.length) {
        for (var i = 0, l = obj.length; i < l; i++) {
          if (iterator.call(context, obj[i], i, obj) === false) return false;
        }
      } else {
        for (var key in obj) {
          if (obj.hasOwnProperty(key)) {
            if (iterator.call(context, obj[key], key, obj) === false) return false;
          }
        }
      }
    },
    makeInstance: function (obj) {
      var noop = new Function();
      noop.prototype = obj;
      obj = new noop();
      noop.prototype = null;
      return obj;
    },
    isObject: function (item) {
      return item && typeof item === 'object' && !Array.isArray(item);
    },
    merge: function (target, source) {
      var output = Object.assign({}, target);
      if (this.isObject(target) && this.isObject(source)) {
        Object.keys(source).forEach((key) => {
          if (this.isObject(source[key])) {
            if (!(key in target)) {
              Object.assign(output, { [key]: source[key] });
            } else {
              output[key] = this.merge(target[key], source[key]);
            }
          } else {
            Object.assign(output, { [key]: source[key] });
          }
        });
      }
      return output;
    },
    extend: function (t, s, b) {
      if (s) {
        for (var k in s) {
          if (!b || !t.hasOwnProperty(k)) {
            t[k] = s[k];
          }
        }
      }
      return t;
    },
    extend2: function (t) {
      var a = arguments;
      for (var i = 1; i < a.length; i++) {
        var x = a[i];
        for (var k in x) {
          if (!t.hasOwnProperty(k)) {
            t[k] = x[k];
          }
        }
      }
      return t;
    },
    inherits: function (subClass, superClass) {
      var oldP = subClass.prototype,
        newP = utils.makeInstance(superClass.prototype);
      utils.extend(newP, oldP, true);
      subClass.prototype = newP;
      return (newP.constructor = subClass);
    },
    bind: function (fn, context) {
      return function () {
        return fn.apply(context, arguments);
      };
    },
    defer: function (fn, delay, exclusion) {
      var timerID;
      return function () {
        if (exclusion) {
          clearTimeout(timerID);
        }
        timerID = setTimeout(fn, delay);
      };
    },
    indexOf: function (array, item, start) {
      var index = -1;
      start = this.isNumber(start) ? start : 0;
      this.each(array, function (v, i) {
        if (i >= start && v === item) {
          index = i;
          return false;
        }
      });
      return index;
    },
    removeItem: function (array, item) {
      for (var i = 0, l = array.length; i < l; i++) {
        if (array[i] === item) {
          array.splice(i, 1);
          i--;
        }
      }
    },
    trim: function (str) {
      return str.replace(/(^[ \t\n\r]+)|([ \t\n\r]+$)/g, '');
    },
    listToMap: function (list) {
      if (!list) return {};
      list = utils.isArray(list) ? list : list.split(',');
      for (var i = 0, ci, obj = {}; (ci = list[i++]); ) {
        obj[ci.toUpperCase()] = obj[ci] = 1;
      }
      return obj;
    },
    unhtml: function (str, reg) {
      return str
        ? str.replace(reg || /[&<">'](?:(amp|lt|ldquo|rdquo|quot|gt|#39|nbsp|#\d+);)?/g, function (a, b) {
            if (b) {
              return a;
            } else {
              return {
                '<': '&lt;',
                '&': '&amp;',
                '"': '&quot;',
                '“': '&ldquo;',
                '”': '&rdquo;',
                '>': '&gt;',
                "'": '&#39;',
              }[a];
            }
          })
        : '';
    },
    html: function (str) {
      return str
        ? str.replace(/&((g|l|quo|ldquo|rdquo)t|amp|#39|nbsp);/g, function (m) {
            return {
              '&lt;': '<',
              '&amp;': '&',
              '&quot;': '"',
              '&ldquo;': '“',
              '&rdquo;': '”',
              '&gt;': '>',
              '&#39;': "'",
              '&nbsp;': ' ',
            }[m];
          })
        : '';
    },
    cssStyleToDomStyle: (function () {
      var test = document.createElement('div').style,
        cache = {
          float: test.cssFloat !== undefined ? 'cssFloat' : test.styleFloat !== undefined ? 'styleFloat' : 'float',
        };
      return function (cssName) {
        return (
          cache[cssName] ||
          (cache[cssName] = cssName.toLowerCase().replace(/-./g, function (match) {
            return match.charAt(1).toUpperCase();
          }))
        );
      };
    })(),
    loadFile: (function () {
      var tmpList = [];
      function getItem(doc, obj) {
        try {
          for (var i = 0, ci; (ci = tmpList[i++]); ) {
            if (ci.doc === doc && ci.url == (obj.src || obj.href)) {
              return ci;
            }
          }
        } catch (e) {
          return null;
        }
      }
      return function (doc, obj, fn) {
        var item = getItem(doc, obj);
        if (item) {
          if (item.ready) {
            fn && fn();
          } else {
            item.funs.push(fn);
          }
          return;
        }
        tmpList.push({ doc: doc, url: obj.src || obj.href, funs: [fn] });
        if (!doc.body) {
          var html = [];
          for (var p in obj) {
            if (p == 'tag') continue;
            html.push(p + '="' + obj[p] + '"');
          }
          doc.write('<' + obj.tag + ' ' + html.join(' ') + ' ></' + obj.tag + '>');
          return;
        }
        if (obj.id && doc.getElementById(obj.id)) {
          return;
        }
        var element = doc.createElement(obj.tag);
        delete obj.tag;
        for (var p in obj) {
          element.setAttribute(p, obj[p]);
        }
        element.onload = element.onreadystatechange = function () {
          if (!this.readyState || /loaded|complete/.test(this.readyState)) {
            item = getItem(doc, obj);
            if (item.funs.length > 0) {
              item.ready = 1;
              for (var fi; (fi = item.funs.pop()); ) {
                fi();
              }
            }
            element.onload = element.onreadystatechange = null;
          }
        };
        element.onerror = function () {
          throw Error('The load ' + (obj.href || obj.src) + ' fails,check the url settings of file ueditor.config.js ');
        };
        doc.getElementsByTagName('head')[0].appendChild(element);
      };
    })(),
    isEmptyObject: function (obj) {
      if (obj == null) return true;
      if (this.isArray(obj) || this.isString(obj)) return obj.length === 0;
      for (var key in obj) if (obj.hasOwnProperty(key)) return false;
      return true;
    },
    fixColor: function (name, value) {
      if (/color/i.test(name) && /rgba?/.test(value)) {
        var array = value.split(',');
        if (array.length > 3) return '';
        value = '#';
        for (var i = 0, color; (color = array[i++]); ) {
          color = parseInt(color.replace(/[^\d]/gi, ''), 10).toString(16);
          value += color.length == 1 ? '0' + color : color;
        }
        value = value.toUpperCase();
      }
      return value;
    },
    optCss: function (val) {
      var padding, margin, border;
      val = val.replace(/(padding|margin|border)\-([^:]+):([^;]+);?/gi, function (str, key, name, val) {
        if (val.split(' ').length == 1) {
          switch (key) {
            case 'padding':
              !padding && (padding = {});
              padding[name] = val;
              return '';
            case 'margin':
              !margin && (margin = {});
              margin[name] = val;
              return '';
            case 'border':
              return val == 'initial' ? '' : str;
          }
        }
        return str;
      });
      function opt(obj, name) {
        if (!obj) {
          return '';
        }
        var t = obj.top,
          b = obj.bottom,
          l = obj.left,
          r = obj.right,
          val = '';
        if (!t || !l || !b || !r) {
          for (var p in obj) {
            val += ';' + name + '-' + p + ':' + obj[p] + ';';
          }
        } else {
          val +=
            ';' +
            name +
            ':' +
            (t == b && b == l && l == r
              ? t
              : t == b && l == r
                ? t + ' ' + l
                : l == r
                  ? t + ' ' + l + ' ' + b
                  : t + ' ' + r + ' ' + b + ' ' + l) +
            ';';
        }
        return val;
      }
      val += opt(padding, 'padding') + opt(margin, 'margin');
      return val
        .replace(/^[ \n\r\t;]*|[ \n\r\t]*$/, '')
        .replace(/;([ \n\r\t]+)|\1;/g, ';')
        .replace(/(&((l|g)t|quot|#39))?;{2,}/g, function (a, b) {
          return b ? b + ';;' : ';';
        });
    },
    clone: function (source, target) {
      var tmp;
      target = target || {};
      for (var i in source) {
        if (source.hasOwnProperty(i)) {
          tmp = source[i];
          if (typeof tmp == 'object') {
            target[i] = utils.isArray(tmp) ? [] : {};
            utils.clone(source[i], target[i]);
          } else {
            target[i] = tmp;
          }
        }
      }
      return target;
    },
    transUnitToPx: function (val) {
      if (!/(pt|cm)/.test(val)) {
        return val;
      }
      var unit;
      val.replace(/([\d.]+)(\w+)/, function (str, v, u) {
        val = v;
        unit = u;
      });
      switch (unit) {
        case 'cm':
          val = parseFloat(val) * 25;
          break;
        case 'pt':
          val = Math.round((parseFloat(val) * 96) / 72);
      }
      return val + (val ? 'px' : '');
    },
    domReady: (function () {
      var fnArr = [];
      function doReady(doc) {
        doc.isReady = true;
        for (var ci; (ci = fnArr.pop()); ci()) {}
      }
      return function (onready, win) {
        win = win || window;
        var doc = win.document;
        onready && fnArr.push(onready);
        if (doc.readyState === 'complete') {
          doReady(doc);
        } else {
          doc.isReady && doReady(doc);
          if (browser.ie && browser.version != 11) {
            (function () {
              if (doc.isReady) return;
              try {
                doc.documentElement.doScroll('left');
              } catch (error) {
                setTimeout(arguments.callee, 0);
                return;
              }
              doReady(doc);
            })();
            win.attachEvent('onload', function () {
              doReady(doc);
            });
          } else {
            doc.addEventListener(
              'DOMContentLoaded',
              function () {
                doc.removeEventListener('DOMContentLoaded', arguments.callee, false);
                doReady(doc);
              },
              false,
            );
            win.addEventListener(
              'load',
              function () {
                doReady(doc);
              },
              false,
            );
          }
        }
      };
    })(),
    cssRule:
      browser.ie && browser.version != 11
        ? function (key, style, doc) {
            var indexList, index;
            if (style === undefined || (style && style.nodeType && style.nodeType == 9)) {
              doc = style && style.nodeType && style.nodeType == 9 ? style : doc || document;
              indexList = doc.indexList || (doc.indexList = {});
              index = indexList[key];
              if (index !== undefined) {
                return doc.styleSheets[index].cssText;
              }
              return undefined;
            }
            doc = doc || document;
            indexList = doc.indexList || (doc.indexList = {});
            index = indexList[key];
            if (style === '') {
              if (index !== undefined) {
                doc.styleSheets[index].cssText = '';
                delete indexList[key];
                return true;
              }
              return false;
            }
            if (index !== undefined) {
              sheetStyle = doc.styleSheets[index];
            } else {
              sheetStyle = doc.createStyleSheet('', (index = doc.styleSheets.length));
              indexList[key] = index;
            }
            sheetStyle.cssText = style;
          }
        : function (key, style, doc) {
            var head, node;
            if (style === undefined || (style && style.nodeType && style.nodeType == 9)) {
              doc = style && style.nodeType && style.nodeType == 9 ? style : doc || document;
              node = doc.getElementById(key);
              return node ? node.innerHTML : undefined;
            }
            doc = doc || document;
            node = doc.getElementById(key);
            if (style === '') {
              if (node) {
                node.parentNode.removeChild(node);
                return true;
              }
              return false;
            }
            if (node) {
              node.innerHTML = style;
            } else {
              node = doc.createElement('style');
              node.id = key;
              node.innerHTML = style;
              doc.getElementsByTagName('head')[0].appendChild(node);
            }
          },
    sort: function (array, compareFn) {
      compareFn =
        compareFn ||
        function (item1, item2) {
          return item1.localeCompare(item2);
        };
      for (var i = 0, len = array.length; i < len; i++) {
        for (var j = i, length = array.length; j < length; j++) {
          if (compareFn(array[i], array[j]) > 0) {
            var t = array[i];
            array[i] = array[j];
            array[j] = t;
          }
        }
      }
      return array;
    },
    serializeParam: function (json) {
      var strArr = [];
      for (var i in json) {
        if (i == 'method' || i == 'timeout' || i == 'async') continue;
        if (!((typeof json[i]).toLowerCase() == 'function' || (typeof json[i]).toLowerCase() == 'object')) {
          strArr.push(encodeURIComponent(i) + '=' + encodeURIComponent(json[i]));
        } else if (utils.isArray(json[i])) {
          for (var j = 0; j < json[i].length; j++) {
            strArr.push(encodeURIComponent(i) + '[]=' + encodeURIComponent(json[i][j]));
          }
        }
      }
      return strArr.join('&');
    },
    formatUrl: function (url) {
      var u = url.replace(/&&/g, '&');
      u = u.replace(/\?&/g, '?');
      u = u.replace(/&$/g, '');
      u = u.replace(/&#/g, '#');
      u = u.replace(/&+/g, '&');
      return u;
    },
    addStyleContent: function (cssContent) {
      var style = document.createElement('style');
      style.innerHTML = cssContent;
      document.head.appendChild(style);
    },
    isCrossDomainUrl: function (url) {
      var a = document.createElement('a');
      a.href = url;
      if (browser.ie) {
        a.href = a.href;
      }
      return !(
        a.protocol == location.protocol &&
        a.hostname == location.hostname &&
        (a.port == location.port || (a.port == '80' && location.port == '') || (a.port == '' && location.port == '80'))
      );
    },
    clearEmptyAttrs: function (obj) {
      for (var p in obj) {
        if (obj[p] === '') {
          delete obj[p];
        }
      }
      return obj;
    },
    str2json: function (s) {
      if (!utils.isString(s)) return null;
      if (window.JSON) {
        return JSON.parse(s);
      } else {
        return new Function('return ' + utils.trim(s || ''))();
      }
    },
    base64toBlob: function (base64Data, contentType) {
      contentType = contentType || '';
      var sliceSize = 1024;
      var byteCharacters = atob(base64Data);
      var bytesLength = byteCharacters.length;
      var slicesCount = Math.ceil(bytesLength / sliceSize);
      var byteArrays = new Array(slicesCount);
      for (var sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
        var begin = sliceIndex * sliceSize;
        var end = Math.min(begin + sliceSize, bytesLength);
        var bytes = new Array(end - begin);
        for (var offset = begin, i = 0; offset < end; ++i, ++offset) {
          bytes[i] = byteCharacters[offset].charCodeAt(0);
        }
        byteArrays[sliceIndex] = new Uint8Array(bytes);
      }
      return new Blob(byteArrays, { type: contentType });
    },
    json2str: (function () {
      if (window.JSON) {
        return JSON.stringify;
      } else {
        var escapeMap = { '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"': '\\"', '\\': '\\\\' };
        function encodeString(source) {
          if (/["\\\x00-\x1f]/.test(source)) {
            source = source.replace(/["\\\x00-\x1f]/g, function (match) {
              var c = escapeMap[match];
              if (c) {
                return c;
              }
              c = match.charCodeAt();
              return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
            });
          }
          return '"' + source + '"';
        }
        function encodeArray(source) {
          var result = ['['],
            l = source.length,
            preComma,
            i,
            item;
          for (i = 0; i < l; i++) {
            item = source[i];
            switch (typeof item) {
              case 'undefined':
              case 'function':
              case 'unknown':
                break;
              default:
                if (preComma) {
                  result.push(',');
                }
                result.push(utils.json2str(item));
                preComma = 1;
            }
          }
          result.push(']');
          return result.join('');
        }
        function pad(source) {
          return source < 10 ? '0' + source : source;
        }
        function encodeDate(source) {
          return (
            '"' +
            source.getFullYear() +
            '-' +
            pad(source.getMonth() + 1) +
            '-' +
            pad(source.getDate()) +
            'T' +
            pad(source.getHours()) +
            ':' +
            pad(source.getMinutes()) +
            ':' +
            pad(source.getSeconds()) +
            '"'
          );
        }
        return function (value) {
          switch (typeof value) {
            case 'undefined':
              return 'undefined';
            case 'number':
              return isFinite(value) ? String(value) : 'null';
            case 'string':
              return encodeString(value);
            case 'boolean':
              return String(value);
            default:
              if (value === null) {
                return 'null';
              } else if (utils.isArray(value)) {
                return encodeArray(value);
              } else if (utils.isDate(value)) {
                return encodeDate(value);
              } else {
                var result = ['{'],
                  encode = utils.json2str,
                  preComma,
                  item;
                for (var key in value) {
                  if (Object.prototype.hasOwnProperty.call(value, key)) {
                    item = value[key];
                    switch (typeof item) {
                      case 'undefined':
                      case 'unknown':
                      case 'function':
                        break;
                      default:
                        if (preComma) {
                          result.push(',');
                        }
                        preComma = 1;
                        result.push(encode(key) + ':' + encode(item));
                    }
                  }
                }
                result.push('}');
                return result.join('');
              }
          }
        };
      }
    })(),
  });
  utils.each(['String', 'Function', 'Array', 'Number', 'RegExp', 'Object', 'Date'], function (v) {
    UE.utils['is' + v] = function (obj) {
      return Object.prototype.toString.apply(obj) == '[object ' + v + ']';
    };
  });
  var EventBase = (UE.EventBase = function () {});
  EventBase.prototype = {
    addListener: function (types, listener) {
      types = utils.trim(types).split(/\s+/);
      for (var i = 0, ti; (ti = types[i++]); ) {
        getListener(this, ti, true).push(listener);
      }
    },
    on: function (types, listener) {
      return this.addListener(types, listener);
    },
    off: function (types, listener) {
      return this.removeListener(types, listener);
    },
    trigger: function () {
      return this.fireEvent.apply(this, arguments);
    },
    removeListener: function (types, listener) {
      types = utils.trim(types).split(/\s+/);
      for (var i = 0, ti; (ti = types[i++]); ) {
        utils.removeItem(getListener(this, ti) || [], listener);
      }
    },
    fireEvent: function () {
      var types = arguments[0];
      types = utils.trim(types).split(' ');
      for (var i = 0, ti; (ti = types[i++]); ) {
        var listeners = getListener(this, ti),
          r,
          t,
          k;
        if (listeners) {
          k = listeners.length;
          while (k--) {
            if (!listeners[k]) continue;
            t = listeners[k].apply(this, arguments);
            if (t === true) {
              return t;
            }
            if (t !== undefined) {
              r = t;
            }
          }
        }
        if ((t = this['on' + ti.toLowerCase()])) {
          r = t.apply(this, arguments);
        }
      }
      return r;
    },
  };
  function getListener(obj, type, force) {
    var allListeners;
    type = type.toLowerCase();
    return (
      (allListeners = obj.__allListeners || (force && (obj.__allListeners = {}))) &&
      (allListeners[type] || (force && (allListeners[type] = [])))
    );
  }
  var dtd = (dom.dtd = (function () {
    function _(s) {
      for (var k in s) {
        s[k.toUpperCase()] = s[k];
      }
      return s;
    }
    var X = utils.extend2;
    var A = _({ isindex: 1, fieldset: 1 }),
      B = _({ input: 1, button: 1, select: 1, textarea: 1, label: 1 }),
      C = X(_({ a: 1 }), B),
      D = X({ iframe: 1 }, C),
      E = _({
        hr: 1,
        ul: 1,
        menu: 1,
        div: 1,
        blockquote: 1,
        noscript: 1,
        table: 1,
        center: 1,
        address: 1,
        dir: 1,
        pre: 1,
        h5: 1,
        dl: 1,
        h4: 1,
        noframes: 1,
        h6: 1,
        ol: 1,
        h1: 1,
        h3: 1,
        h2: 1,
      }),
      F = _({ ins: 1, del: 1, script: 1, style: 1 }),
      G = X(
        _({
          mark: 1,
          b: 1,
          acronym: 1,
          bdo: 1,
          var: 1,
          '#': 1,
          abbr: 1,
          code: 1,
          br: 1,
          i: 1,
          cite: 1,
          kbd: 1,
          u: 1,
          strike: 1,
          s: 1,
          tt: 1,
          strong: 1,
          q: 1,
          samp: 1,
          em: 1,
          dfn: 1,
          span: 1,
        }),
        F,
      ),
      H = X(
        _({ sub: 1, img: 1, embed: 1, object: 1, sup: 1, basefont: 1, map: 1, applet: 1, font: 1, big: 1, small: 1 }),
        G,
      ),
      I = X(_({ p: 1 }), H),
      J = X(_({ iframe: 1 }), H, B),
      K = _({
        img: 1,
        embed: 1,
        noscript: 1,
        br: 1,
        kbd: 1,
        center: 1,
        button: 1,
        basefont: 1,
        h5: 1,
        h4: 1,
        samp: 1,
        h6: 1,
        ol: 1,
        h1: 1,
        h3: 1,
        h2: 1,
        form: 1,
        font: 1,
        '#': 1,
        select: 1,
        menu: 1,
        ins: 1,
        abbr: 1,
        label: 1,
        code: 1,
        table: 1,
        script: 1,
        cite: 1,
        input: 1,
        iframe: 1,
        strong: 1,
        textarea: 1,
        noframes: 1,
        big: 1,
        small: 1,
        span: 1,
        hr: 1,
        sub: 1,
        bdo: 1,
        var: 1,
        div: 1,
        object: 1,
        sup: 1,
        strike: 1,
        dir: 1,
        map: 1,
        dl: 1,
        applet: 1,
        del: 1,
        isindex: 1,
        fieldset: 1,
        ul: 1,
        b: 1,
        acronym: 1,
        a: 1,
        blockquote: 1,
        i: 1,
        u: 1,
        s: 1,
        tt: 1,
        address: 1,
        q: 1,
        pre: 1,
        p: 1,
        em: 1,
        dfn: 1,
      }),
      L = X(_({ a: 0 }), J),
      M = _({ tr: 1 }),
      N = _({ '#': 1 }),
      O = X(_({ param: 1 }), K),
      P = X(_({ form: 1 }), A, D, E, I),
      Q = _({ li: 1, ol: 1, ul: 1 }),
      R = _({ style: 1, script: 1 }),
      S = _({ base: 1, link: 1, meta: 1, title: 1 }),
      T = X(S, R),
      U = _({ head: 1, body: 1 }),
      V = _({ html: 1 });
    var block = _({
        address: 1,
        blockquote: 1,
        center: 1,
        dir: 1,
        div: 1,
        dl: 1,
        fieldset: 1,
        form: 1,
        h1: 1,
        h2: 1,
        h3: 1,
        h4: 1,
        h5: 1,
        h6: 1,
        hr: 1,
        isindex: 1,
        menu: 1,
        noframes: 1,
        ol: 1,
        p: 1,
        pre: 1,
        table: 1,
        ul: 1,
      }),
      empty = _({
        area: 1,
        base: 1,
        basefont: 1,
        br: 1,
        col: 1,
        command: 1,
        dialog: 1,
        embed: 1,
        hr: 1,
        img: 1,
        input: 1,
        isindex: 1,
        keygen: 1,
        link: 1,
        meta: 1,
        param: 1,
        source: 1,
        track: 1,
        wbr: 1,
      });
    return _({
      $nonBodyContent: X(V, U, S),
      $block: block,
      $inline: L,
      $inlineWithA: X(_({ a: 1 }), L),
      $body: X(_({ script: 1, style: 1 }), block),
      $cdata: _({ script: 1, style: 1 }),
      $empty: empty,
      $nonChild: _({ iframe: 1, textarea: 1 }),
      $listItem: _({ dd: 1, dt: 1, li: 1 }),
      $list: _({ ul: 1, ol: 1, dl: 1 }),
      $isNotEmpty: _({
        table: 1,
        ul: 1,
        ol: 1,
        dl: 1,
        iframe: 1,
        area: 1,
        base: 1,
        col: 1,
        hr: 1,
        img: 1,
        embed: 1,
        input: 1,
        textarea: 1,
        link: 1,
        meta: 1,
        param: 1,
        h1: 1,
        h2: 1,
        h3: 1,
        h4: 1,
        h5: 1,
        h6: 1,
      }),
      $removeEmpty: _({
        a: 1,
        abbr: 1,
        acronym: 1,
        address: 1,
        b: 1,
        bdo: 1,
        big: 1,
        cite: 1,
        code: 1,
        del: 1,
        dfn: 1,
        em: 1,
        font: 1,
        i: 1,
        ins: 1,
        label: 1,
        kbd: 1,
        q: 1,
        s: 1,
        samp: 1,
        small: 1,
        span: 1,
        strike: 1,
        strong: 1,
        sub: 1,
        sup: 1,
        tt: 1,
        u: 1,
        var: 1,
      }),
      $removeEmptyBlock: _({ p: 1, div: 1 }),
      $tableContent: _({
        caption: 1,
        col: 1,
        colgroup: 1,
        tbody: 1,
        td: 1,
        tfoot: 1,
        th: 1,
        thead: 1,
        tr: 1,
        table: 1,
      }),
      $notTransContent: _({ pre: 1, script: 1, style: 1, textarea: 1 }),
      html: U,
      head: T,
      style: N,
      script: N,
      body: P,
      base: {},
      link: {},
      meta: {},
      title: N,
      col: {},
      tr: _({ td: 1, th: 1 }),
      img: {},
      embed: {},
      colgroup: _({ thead: 1, col: 1, tbody: 1, tr: 1, tfoot: 1 }),
      noscript: P,
      td: P,
      br: {},
      th: P,
      center: P,
      kbd: L,
      button: X(I, E),
      basefont: {},
      h5: L,
      h4: L,
      samp: L,
      h6: L,
      ol: Q,
      h1: L,
      h3: L,
      option: N,
      h2: L,
      form: X(A, D, E, I),
      select: _({ optgroup: 1, option: 1 }),
      font: L,
      ins: L,
      menu: Q,
      abbr: L,
      label: L,
      table: _({ thead: 1, col: 1, tbody: 1, tr: 1, colgroup: 1, caption: 1, tfoot: 1 }),
      code: L,
      tfoot: M,
      cite: L,
      li: P,
      input: {},
      iframe: P,
      strong: L,
      textarea: N,
      noframes: P,
      big: L,
      small: L,
      span: _({ '#': 1, br: 1, b: 1, strong: 1, u: 1, i: 1, em: 1, sub: 1, sup: 1, strike: 1, span: 1 }),
      hr: L,
      dt: L,
      sub: L,
      optgroup: _({ option: 1 }),
      param: {},
      bdo: L,
      var: L,
      div: P,
      object: O,
      sup: L,
      dd: P,
      strike: L,
      area: {},
      dir: Q,
      map: X(_({ area: 1, form: 1, p: 1 }), A, F, E),
      applet: O,
      dl: _({ dt: 1, dd: 1 }),
      del: L,
      isindex: {},
      fieldset: X(_({ legend: 1 }), K),
      thead: M,
      ul: Q,
      acronym: L,
      b: L,
      a: X(_({ a: 1 }), J),
      blockquote: X(_({ td: 1, tr: 1, tbody: 1, li: 1 }), P),
      caption: L,
      i: L,
      u: L,
      tbody: M,
      s: L,
      address: X(D, I),
      tt: L,
      legend: L,
      q: L,
      pre: X(G, C),
      p: X(_({ a: 1 }), L),
      em: L,
      dfn: L,
      mark: L,
    });
  })());
  function getDomNode(node, start, ltr, startFromChild, fn, guard) {
    var tmpNode = startFromChild && node[start],
      parent;
    !tmpNode && (tmpNode = node[ltr]);
    while (!tmpNode && (parent = (parent || node).parentNode)) {
      if (parent.tagName == 'BODY' || (guard && !guard(parent))) {
        return null;
      }
      tmpNode = parent[ltr];
    }
    if (tmpNode && fn && !fn(tmpNode)) {
      return getDomNode(tmpNode, start, ltr, false, fn);
    }
    return tmpNode;
  }
  var attrFix =
      ie && browser.version < 9
        ? {
            tabindex: 'tabIndex',
            readonly: 'readOnly',
            for: 'htmlFor',
            class: 'className',
            maxlength: 'maxLength',
            cellspacing: 'cellSpacing',
            cellpadding: 'cellPadding',
            rowspan: 'rowSpan',
            colspan: 'colSpan',
            usemap: 'useMap',
            frameborder: 'frameBorder',
          }
        : { tabindex: 'tabIndex', readonly: 'readOnly' },
    styleBlock = utils.listToMap([
      '-webkit-box',
      '-moz-box',
      'block',
      'list-item',
      'table',
      'table-row-group',
      'table-header-group',
      'table-footer-group',
      'table-row',
      'table-column-group',
      'table-column',
      'table-cell',
      'table-caption',
    ]);
  var domUtils = (dom.domUtils = {
    NODE_ELEMENT: 1,
    NODE_DOCUMENT: 9,
    NODE_TEXT: 3,
    NODE_COMMENT: 8,
    NODE_DOCUMENT_FRAGMENT: 11,
    POSITION_IDENTICAL: 0,
    POSITION_DISCONNECTED: 1,
    POSITION_FOLLOWING: 2,
    POSITION_PRECEDING: 4,
    POSITION_IS_CONTAINED: 8,
    POSITION_CONTAINS: 16,
    fillChar: ie && browser.version === '6' ? '\ufeff' : '​',
    keys: { 8: 1, 46: 1, 16: 1, 17: 1, 18: 1, 37: 1, 38: 1, 39: 1, 40: 1, 13: 1 },
    getPosition: function (nodeA, nodeB) {
      if (nodeA === nodeB) {
        return 0;
      }
      var node,
        parentsA = [nodeA],
        parentsB = [nodeB];
      node = nodeA;
      while ((node = node.parentNode)) {
        if (node === nodeB) {
          return 10;
        }
        parentsA.push(node);
      }
      node = nodeB;
      while ((node = node.parentNode)) {
        if (node === nodeA) {
          return 20;
        }
        parentsB.push(node);
      }
      parentsA.reverse();
      parentsB.reverse();
      if (parentsA[0] !== parentsB[0]) {
        return 1;
      }
      var i = -1;
      while ((i++, parentsA[i] === parentsB[i])) {}
      nodeA = parentsA[i];
      nodeB = parentsB[i];
      while ((nodeA = nodeA.nextSibling)) {
        if (nodeA === nodeB) {
          return 4;
        }
      }
      return 2;
    },
    getNodeIndex: function (node, ignoreTextNode) {
      var preNode = node,
        i = 0;
      while ((preNode = preNode.previousSibling)) {
        if (ignoreTextNode && preNode.nodeType == 3) {
          if (preNode.nodeType != preNode.nextSibling.nodeType) {
            i++;
          }
          continue;
        }
        i++;
      }
      return i;
    },
    inDoc: function (node, doc) {
      return domUtils.getPosition(node, doc) === 10;
    },
    findParent: function (node, filterFn, includeSelf) {
      if (node && !domUtils.isBody(node)) {
        node = includeSelf ? node : node.parentNode;
        while (node) {
          if (!filterFn || filterFn(node) || domUtils.isBody(node)) {
            return filterFn && !filterFn(node) && domUtils.isBody(node) ? null : node;
          }
          node = node.parentNode;
        }
      }
      return null;
    },
    findParentByTagName: function (node, tagNames, includeSelf, excludeFn) {
      tagNames = utils.listToMap(utils.isArray(tagNames) ? tagNames : [tagNames]);
      return domUtils.findParent(
        node,
        function (node) {
          return tagNames[node.tagName] && !(excludeFn && excludeFn(node));
        },
        includeSelf,
      );
    },
    findParents: function (node, includeSelf, filterFn, closerFirst) {
      var parents = includeSelf && ((filterFn && filterFn(node)) || !filterFn) ? [node] : [];
      while ((node = domUtils.findParent(node, filterFn))) {
        parents.push(node);
      }
      return closerFirst ? parents : parents.reverse();
    },
    insertAfter: function (node, newNode) {
      return node.nextSibling
        ? node.parentNode.insertBefore(newNode, node.nextSibling)
        : node.parentNode.appendChild(newNode);
    },
    remove: function (node, keepChildren) {
      var parent = node.parentNode,
        child;
      if (parent) {
        if (keepChildren && node.hasChildNodes()) {
          while ((child = node.firstChild)) {
            parent.insertBefore(child, node);
          }
        }
        parent.removeChild(node);
      }
      return node;
    },
    getNextDomNode: function (node, startFromChild, filterFn, guard) {
      return getDomNode(node, 'firstChild', 'nextSibling', startFromChild, filterFn, guard);
    },
    getPreDomNode: function (node, startFromChild, filterFn, guard) {
      return getDomNode(node, 'lastChild', 'previousSibling', startFromChild, filterFn, guard);
    },
    isBookmarkNode: function (node) {
      return node.nodeType == 1 && node.id && /^_baidu_bookmark_/i.test(node.id);
    },
    getWindow: function (node) {
      var doc = node.ownerDocument || node;
      return doc.defaultView || doc.parentWindow;
    },
    getCommonAncestor: function (nodeA, nodeB) {
      if (nodeA === nodeB) return nodeA;
      var parentsA = [nodeA],
        parentsB = [nodeB],
        parent = nodeA,
        i = -1;
      while ((parent = parent.parentNode)) {
        if (parent === nodeB) {
          return parent;
        }
        parentsA.push(parent);
      }
      parent = nodeB;
      while ((parent = parent.parentNode)) {
        if (parent === nodeA) return parent;
        parentsB.push(parent);
      }
      parentsA.reverse();
      parentsB.reverse();
      while ((i++, parentsA[i] === parentsB[i])) {}
      return i == 0 ? null : parentsA[i - 1];
    },
    clearEmptySibling: function (node, ignoreNext, ignorePre) {
      function clear(next, dir) {
        var tmpNode;
        while (
          next &&
          !domUtils.isBookmarkNode(next) &&
          (domUtils.isEmptyInlineElement(next) ||
            !new RegExp('[^\t\n\r' + domUtils.fillChar + ']').test(next.nodeValue))
        ) {
          tmpNode = next[dir];
          domUtils.remove(next);
          next = tmpNode;
        }
      }
      !ignoreNext && clear(node.nextSibling, 'nextSibling');
      !ignorePre && clear(node.previousSibling, 'previousSibling');
    },
    split: function (node, offset) {
      var doc = node.ownerDocument;
      if (browser.ie && offset == node.nodeValue.length) {
        var next = doc.createTextNode('');
        return domUtils.insertAfter(node, next);
      }
      var retval = node.splitText(offset);
      if (browser.ie8) {
        var tmpNode = doc.createTextNode('');
        domUtils.insertAfter(retval, tmpNode);
        domUtils.remove(tmpNode);
      }
      return retval;
    },
    isWhitespace: function (node) {
      return !new RegExp('[^ \t\n\r' + domUtils.fillChar + ']').test(node.nodeValue);
    },
    getXY: function (element) {
      var x = 0,
        y = 0;
      while (element.offsetParent) {
        y += element.offsetTop;
        x += element.offsetLeft;
        element = element.offsetParent;
      }
      return { x: x, y: y };
    },
    on: function (element, type, handler) {
      var types = utils.isArray(type) ? type : utils.trim(type).split(/\s+/),
        k = types.length;
      if (k)
        while (k--) {
          type = types[k];
          if (element.addEventListener) {
            element.addEventListener(type, handler, false);
          } else {
            if (!handler._d) {
              handler._d = { els: [] };
            }
            var key = type + handler.toString(),
              index = utils.indexOf(handler._d.els, element);
            if (!handler._d[key] || index == -1) {
              if (index == -1) {
                handler._d.els.push(element);
              }
              if (!handler._d[key]) {
                handler._d[key] = function (evt) {
                  return handler.call(evt.srcElement, evt || window.event);
                };
              }
              element.attachEvent('on' + type, handler._d[key]);
            }
          }
        }
      element = null;
    },
    un: function (element, type, handler) {
      var types = utils.isArray(type) ? type : utils.trim(type).split(/\s+/),
        k = types.length;
      if (k)
        while (k--) {
          type = types[k];
          if (element.removeEventListener) {
            element.removeEventListener(type, handler, false);
          } else {
            var key = type + handler.toString();
            try {
              element.detachEvent('on' + type, handler._d ? handler._d[key] : handler);
            } catch (e) {}
            if (handler._d && handler._d[key]) {
              var index = utils.indexOf(handler._d.els, element);
              if (index != -1) {
                handler._d.els.splice(index, 1);
              }
              handler._d.els.length == 0 && delete handler._d[key];
            }
          }
        }
    },
    isSameElement: function (nodeA, nodeB) {
      if (nodeA.tagName != nodeB.tagName) {
        return false;
      }
      var thisAttrs = nodeA.attributes,
        otherAttrs = nodeB.attributes;
      if (!ie && thisAttrs.length != otherAttrs.length) {
        return false;
      }
      var attrA,
        attrB,
        al = 0,
        bl = 0;
      for (var i = 0; (attrA = thisAttrs[i++]); ) {
        if (attrA.nodeName == 'style') {
          if (attrA.specified) {
            al++;
          }
          if (domUtils.isSameStyle(nodeA, nodeB)) {
            continue;
          } else {
            return false;
          }
        }
        if (ie) {
          if (attrA.specified) {
            al++;
            attrB = otherAttrs.getNamedItem(attrA.nodeName);
          } else {
            continue;
          }
        } else {
          attrB = nodeB.attributes[attrA.nodeName];
        }
        if (!attrB.specified || attrA.nodeValue != attrB.nodeValue) {
          return false;
        }
      }
      if (ie) {
        for (i = 0; (attrB = otherAttrs[i++]); ) {
          if (attrB.specified) {
            bl++;
          }
        }
        if (al != bl) {
          return false;
        }
      }
      return true;
    },
    isSameStyle: function (nodeA, nodeB) {
      var styleA = nodeA.style.cssText.replace(/( ?; ?)/g, ';').replace(/( ?: ?)/g, ':'),
        styleB = nodeB.style.cssText.replace(/( ?; ?)/g, ';').replace(/( ?: ?)/g, ':');
      if (browser.opera) {
        styleA = nodeA.style;
        styleB = nodeB.style;
        if (styleA.length != styleB.length) return false;
        for (var p in styleA) {
          if (/^(\d+|csstext)$/i.test(p)) {
            continue;
          }
          if (styleA[p] != styleB[p]) {
            return false;
          }
        }
        return true;
      }
      if (!styleA || !styleB) {
        return styleA == styleB;
      }
      styleA = styleA.split(';');
      styleB = styleB.split(';');
      if (styleA.length != styleB.length) {
        return false;
      }
      for (var i = 0, ci; (ci = styleA[i++]); ) {
        if (utils.indexOf(styleB, ci) == -1) {
          return false;
        }
      }
      return true;
    },
    isBlockElm: function (node) {
      return (
        node.nodeType == 1 &&
        (dtd.$block[node.tagName] || styleBlock[domUtils.getComputedStyle(node, 'display')]) &&
        !dtd.$nonChild[node.tagName]
      );
    },
    isBody: function (node) {
      return node && node.nodeType == 1 && node.tagName.toLowerCase() == 'body';
    },
    breakParent: function (node, parent) {
      var tmpNode,
        parentClone = node,
        clone = node,
        leftNodes,
        rightNodes;
      do {
        parentClone = parentClone.parentNode;
        if (leftNodes) {
          tmpNode = parentClone.cloneNode(false);
          tmpNode.appendChild(leftNodes);
          leftNodes = tmpNode;
          tmpNode = parentClone.cloneNode(false);
          tmpNode.appendChild(rightNodes);
          rightNodes = tmpNode;
        } else {
          leftNodes = parentClone.cloneNode(false);
          rightNodes = leftNodes.cloneNode(false);
        }
        while ((tmpNode = clone.previousSibling)) {
          leftNodes.insertBefore(tmpNode, leftNodes.firstChild);
        }
        while ((tmpNode = clone.nextSibling)) {
          rightNodes.appendChild(tmpNode);
        }
        clone = parentClone;
      } while (parent !== parentClone);
      tmpNode = parent.parentNode;
      tmpNode.insertBefore(leftNodes, parent);
      tmpNode.insertBefore(rightNodes, parent);
      tmpNode.insertBefore(node, rightNodes);
      domUtils.remove(parent);
      return node;
    },
    isEmptyInlineElement: function (node) {
      if (node.nodeType != 1 || !dtd.$removeEmpty[node.tagName]) {
        return 0;
      }
      node = node.firstChild;
      while (node) {
        if (domUtils.isBookmarkNode(node)) {
          return 0;
        }
        if (
          (node.nodeType == 1 && !domUtils.isEmptyInlineElement(node)) ||
          (node.nodeType == 3 && !domUtils.isWhitespace(node))
        ) {
          return 0;
        }
        node = node.nextSibling;
      }
      return 1;
    },
    trimWhiteTextNode: function (node) {
      function remove(dir) {
        var child;
        while ((child = node[dir]) && child.nodeType == 3 && domUtils.isWhitespace(child)) {
          node.removeChild(child);
        }
      }
      remove('firstChild');
      remove('lastChild');
    },
    mergeChild: function (node, tagName, attrs) {
      var list = domUtils.getElementsByTagName(node, node.tagName.toLowerCase());
      for (var i = 0, ci; (ci = list[i++]); ) {
        if (!ci.parentNode || domUtils.isBookmarkNode(ci)) {
          continue;
        }
        if (ci.tagName.toLowerCase() == 'span') {
          if (node === ci.parentNode) {
            domUtils.trimWhiteTextNode(node);
            if (node.childNodes.length == 1) {
              node.style.cssText = ci.style.cssText + ';' + node.style.cssText;
              domUtils.remove(ci, true);
              continue;
            }
          }
          ci.style.cssText = node.style.cssText + ';' + ci.style.cssText;
          if (attrs) {
            var style = attrs.style;
            if (style) {
              style = style.split(';');
              for (var j = 0, s; (s = style[j++]); ) {
                ci.style[utils.cssStyleToDomStyle(s.split(':')[0])] = s.split(':')[1];
              }
            }
          }
          if (domUtils.isSameStyle(ci, node)) {
            domUtils.remove(ci, true);
          }
          continue;
        }
        if (domUtils.isSameElement(node, ci)) {
          domUtils.remove(ci, true);
        }
      }
    },
    getElementsByTagName: function (node, tagName, filter) {
      if (filter && utils.isString(filter)) {
        var className = filter;
        filter = function (node) {
          return domUtils.hasClass(node, className);
        };
      }
      tagName = utils
        .trim(tagName)
        .replace(/[ ]{2,}/g, ' ')
        .split(' ');
      var arr = [];
      for (var n = 0, ni; (ni = tagName[n++]); ) {
        var list = node.getElementsByTagName(ni);
        for (var i = 0, ci; (ci = list[i++]); ) {
          if (!filter || filter(ci)) arr.push(ci);
        }
      }
      return arr;
    },
    mergeToParent: function (node) {
      var parent = node.parentNode;
      while (parent && dtd.$removeEmpty[parent.tagName]) {
        if (parent.tagName == node.tagName || parent.tagName == 'A') {
          domUtils.trimWhiteTextNode(parent);
          if (
            (parent.tagName == 'SPAN' && !domUtils.isSameStyle(parent, node)) ||
            (parent.tagName == 'A' && node.tagName == 'SPAN')
          ) {
            if (parent.childNodes.length > 1 || parent !== node.parentNode) {
              node.style.cssText = parent.style.cssText + ';' + node.style.cssText;
              parent = parent.parentNode;
              continue;
            } else {
              parent.style.cssText += ';' + node.style.cssText;
              if (parent.tagName == 'A') {
                parent.style.textDecoration = 'underline';
              }
            }
          }
          if (parent.tagName != 'A') {
            parent === node.parentNode && domUtils.remove(node, true);
            break;
          }
        }
        parent = parent.parentNode;
      }
    },
    mergeSibling: function (node, ignorePre, ignoreNext) {
      function merge(rtl, start, node) {
        var next;
        if (
          (next = node[rtl]) &&
          !domUtils.isBookmarkNode(next) &&
          next.nodeType == 1 &&
          domUtils.isSameElement(node, next)
        ) {
          while (next.firstChild) {
            if (start == 'firstChild') {
              node.insertBefore(next.lastChild, node.firstChild);
            } else {
              node.appendChild(next.firstChild);
            }
          }
          domUtils.remove(next);
        }
      }
      !ignorePre && merge('previousSibling', 'firstChild', node);
      !ignoreNext && merge('nextSibling', 'lastChild', node);
    },
    unSelectable:
      (ie && browser.ie9below) || browser.opera
        ? function (node) {
            node.onselectstart = function () {
              return false;
            };
            node.onclick =
              node.onkeyup =
              node.onkeydown =
                function () {
                  return false;
                };
            node.unselectable = 'on';
            node.setAttribute('unselectable', 'on');
            for (var i = 0, ci; (ci = node.all[i++]); ) {
              switch (ci.tagName.toLowerCase()) {
                case 'iframe':
                case 'textarea':
                case 'input':
                case 'select':
                  break;
                default:
                  ci.unselectable = 'on';
                  node.setAttribute('unselectable', 'on');
              }
            }
          }
        : function (node) {
            node.style.MozUserSelect =
              node.style.webkitUserSelect =
              node.style.msUserSelect =
              node.style.KhtmlUserSelect =
                'none';
          },
    removeAttributes: function (node, attrNames) {
      attrNames = utils.isArray(attrNames)
        ? attrNames
        : utils
            .trim(attrNames)
            .replace(/[ ]{2,}/g, ' ')
            .split(' ');
      for (var i = 0, ci; (ci = attrNames[i++]); ) {
        ci = attrFix[ci] || ci;
        switch (ci) {
          case 'className':
            node[ci] = '';
            break;
          case 'style':
            node.style.cssText = '';
            var val = node.getAttributeNode('style');
            !browser.ie && val && node.removeAttributeNode(val);
        }
        node.removeAttribute(ci);
      }
    },
    createElement: function (doc, tag, attrs) {
      return domUtils.setAttributes(doc.createElement(tag), attrs);
    },
    setAttributes: function (node, attrs) {
      for (var attr in attrs) {
        if ('_propertyDelete' === attr) {
          for (var j = 0; j < attrs[attr].length; j++) {
            if (node.hasAttribute(attrs[attr][j])) {
              node.removeAttribute(attrs[attr][j]);
            }
          }
          continue;
        }
        if (attrs.hasOwnProperty(attr)) {
          var value = attrs[attr];
          switch (attr) {
            case 'class':
              node.className = value;
              break;
            case 'style':
              node.style.cssText = node.style.cssText + ';' + value;
              break;
            case 'innerHTML':
              node[attr] = value;
              break;
            case 'value':
              node.value = value;
              break;
            default:
              node.setAttribute(attrFix[attr] || attr, value);
          }
        }
      }
      return node;
    },
    getComputedStyle: function (element, styleName) {
      var pros = 'width height top left';
      if (pros.indexOf(styleName) > -1) {
        return (
          element[
            'offset' +
              styleName.replace(/^\w/, function (s) {
                return s.toUpperCase();
              })
          ] + 'px'
        );
      }
      if (element.nodeType === 3) {
        element = element.parentNode;
      }
      if (
        browser.ie &&
        browser.version < 9 &&
        styleName === 'font-size' &&
        !element.style.fontSize &&
        !dtd.$empty[element.tagName] &&
        !dtd.$nonChild[element.tagName]
      ) {
        var span = element.ownerDocument.createElement('span');
        span.style.cssText = 'padding:0;border:0;font-family:simsun;';
        span.innerHTML = '.';
        element.appendChild(span);
        var result = span.offsetHeight;
        element.removeChild(span);
        span = null;
        return result + 'px';
      }
      try {
        var value =
          domUtils.getStyle(element, styleName) ||
          (window.getComputedStyle
            ? domUtils.getWindow(element).getComputedStyle(element, '').getPropertyValue(styleName)
            : (element.currentStyle || element.style)[utils.cssStyleToDomStyle(styleName)]);
      } catch (e) {
        return '';
      }
      return utils.transUnitToPx(utils.fixColor(styleName, value));
    },
    removeClasses: function (elm, classNames) {
      classNames = utils.isArray(classNames)
        ? classNames
        : utils
            .trim(classNames)
            .replace(/[ ]{2,}/g, ' ')
            .split(' ');
      for (var i = 0, ci, cls = elm.className; (ci = classNames[i++]); ) {
        cls = cls.replace(new RegExp('\\b' + ci + '\\b'), '');
      }
      cls = utils.trim(cls).replace(/[ ]{2,}/g, ' ');
      if (cls) {
        elm.className = cls;
      } else {
        domUtils.removeAttributes(elm, ['class']);
      }
    },
    addClass: function (elm, classNames) {
      if (!elm) return;
      classNames = utils
        .trim(classNames)
        .replace(/[ ]{2,}/g, ' ')
        .split(' ');
      for (var i = 0, ci, cls = elm.className; (ci = classNames[i++]); ) {
        if (!new RegExp('\\b' + ci + '\\b').test(cls)) {
          cls += ' ' + ci;
        }
      }
      elm.className = utils.trim(cls);
    },
    hasClass: function (element, className) {
      if (utils.isRegExp(className)) {
        return className.test(element.className);
      }
      className = utils
        .trim(className)
        .replace(/[ ]{2,}/g, ' ')
        .split(' ');
      for (var i = 0, ci, cls = element.className; (ci = className[i++]); ) {
        if (!new RegExp('\\b' + ci + '\\b', 'i').test(cls)) {
          return false;
        }
      }
      return i - 1 == className.length;
    },
    preventDefault: function (evt) {
      evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);
    },
    removeStyle: function (element, name) {
      if (browser.ie) {
        if (name == 'color') {
          name = '(^|;)' + name;
        }
        element.style.cssText = element.style.cssText.replace(new RegExp(name + '[^:]*:[^;]+;?', 'ig'), '');
      } else {
        if (element.style.removeProperty) {
          element.style.removeProperty(name);
        } else {
          element.style.removeAttribute(utils.cssStyleToDomStyle(name));
        }
      }
      if (!element.style.cssText) {
        domUtils.removeAttributes(element, ['style']);
      }
    },
    getStyle: function (element, name) {
      var value = element.style[utils.cssStyleToDomStyle(name)];
      return utils.fixColor(name, value);
    },
    setStyle: function (element, name, value) {
      element.style[utils.cssStyleToDomStyle(name)] = value;
      if (!utils.trim(element.style.cssText)) {
        this.removeAttributes(element, 'style');
      }
    },
    setStyles: function (element, styles) {
      for (var name in styles) {
        if (styles.hasOwnProperty(name)) {
          domUtils.setStyle(element, name, styles[name]);
        }
      }
    },
    removeDirtyAttr: function (node) {
      for (var i = 0, ci, nodes = node.getElementsByTagName('*'); (ci = nodes[i++]); ) {
        ci.removeAttribute('_moz_dirty');
      }
      node.removeAttribute('_moz_dirty');
    },
    getChildCount: function (node, fn) {
      var count = 0,
        first = node.firstChild;
      fn =
        fn ||
        function () {
          return 1;
        };
      while (first) {
        if (fn(first)) {
          count++;
        }
        first = first.nextSibling;
      }
      return count;
    },
    isEmptyNode: function (node) {
      return (
        !node.firstChild ||
        domUtils.getChildCount(node, function (node) {
          return !domUtils.isBr(node) && !domUtils.isBookmarkNode(node) && !domUtils.isWhitespace(node);
        }) == 0
      );
    },
    clearSelectedArr: function (nodes) {
      var node;
      while ((node = nodes.pop())) {
        domUtils.removeAttributes(node, ['class']);
      }
    },
    scrollToView: function (node, win, offsetTop) {
      offsetTop = offsetTop || 0;
      var getViewPaneSize = function () {
          var doc = win.document,
            mode = doc.compatMode == 'CSS1Compat';
          return {
            width: (mode ? doc.documentElement.clientWidth : doc.body.clientWidth) || 0,
            height: (mode ? doc.documentElement.clientHeight : doc.body.clientHeight) || 0,
          };
        },
        getScrollPosition = function (win) {
          if ('pageXOffset' in win) {
            return { x: win.pageXOffset || 0, y: win.pageYOffset || 0 };
          } else {
            var doc = win.document;
            return {
              x: doc.documentElement.scrollLeft || doc.body.scrollLeft || 0,
              y: doc.documentElement.scrollTop || doc.body.scrollTop || 0,
            };
          }
        };
      var winHeight = getViewPaneSize().height,
        offset = winHeight * -1 + offsetTop;
      offset += node.offsetHeight || 0;
      var elementPosition = domUtils.getXY(node);
      offset += elementPosition.y;
      var currentScroll = getScrollPosition(win).y;
      if (offset > currentScroll || offset < currentScroll - winHeight) {
        win.scrollTo({ top: offset + (offset < 0 ? -20 : 20), behavior: 'smooth' });
      }
    },
    isBr: function (node) {
      return node.nodeType == 1 && node.tagName == 'BR';
    },
    isFillChar: function (node, isInStart) {
      if (node.nodeType != 3) return false;
      var text = node.nodeValue;
      if (isInStart) {
        return new RegExp('^' + domUtils.fillChar).test(text);
      }
      return !text.replace(new RegExp(domUtils.fillChar, 'g'), '').length;
    },
    isStartInblock: function (range) {
      var tmpRange = range.cloneRange(),
        flag = 0,
        start = tmpRange.startContainer,
        tmp;
      if (start.nodeType == 1 && start.childNodes[tmpRange.startOffset]) {
        start = start.childNodes[tmpRange.startOffset];
        var pre = start.previousSibling;
        while (pre && domUtils.isFillChar(pre)) {
          start = pre;
          pre = pre.previousSibling;
        }
      }
      if (this.isFillChar(start, true) && tmpRange.startOffset == 1) {
        tmpRange.setStartBefore(start);
        start = tmpRange.startContainer;
      }
      while (start && domUtils.isFillChar(start)) {
        tmp = start;
        start = start.previousSibling;
      }
      if (tmp) {
        tmpRange.setStartBefore(tmp);
        start = tmpRange.startContainer;
      }
      if (start.nodeType == 1 && domUtils.isEmptyNode(start) && tmpRange.startOffset == 1) {
        tmpRange.setStart(start, 0).collapse(true);
      }
      while (!tmpRange.startOffset) {
        start = tmpRange.startContainer;
        if (domUtils.isBlockElm(start) || domUtils.isBody(start)) {
          flag = 1;
          break;
        }
        var pre = tmpRange.startContainer.previousSibling,
          tmpNode;
        if (!pre) {
          tmpRange.setStartBefore(tmpRange.startContainer);
        } else {
          while (pre && domUtils.isFillChar(pre)) {
            tmpNode = pre;
            pre = pre.previousSibling;
          }
          if (tmpNode) {
            tmpRange.setStartBefore(tmpNode);
          } else {
            tmpRange.setStartBefore(tmpRange.startContainer);
          }
        }
      }
      return flag && !domUtils.isBody(tmpRange.startContainer) ? 1 : 0;
    },
    isEmptyBlock: function (node, reg) {
      if (node.nodeType != 1) return 0;
      reg = reg || new RegExp('[  \t\r\n' + domUtils.fillChar + ']', 'g');
      if (node[browser.ie ? 'innerText' : 'textContent'].replace(reg, '').length > 0) {
        return 0;
      }
      for (var n in dtd.$isNotEmpty) {
        if (node.getElementsByTagName(n).length) {
          return 0;
        }
      }
      return 1;
    },
    setViewportOffset: function (element, offset) {
      var left = parseInt(element.style.left) | 0;
      var top = parseInt(element.style.top) | 0;
      var rect = element.getBoundingClientRect();
      var offsetLeft = offset.left - rect.left;
      var offsetTop = offset.top - rect.top;
      if (offsetLeft) {
        element.style.left = left + offsetLeft + 'px';
      }
      if (offsetTop) {
        element.style.top = top + offsetTop + 'px';
      }
    },
    fillNode: function (doc, node) {
      var tmpNode = browser.ie ? doc.createTextNode(domUtils.fillChar) : doc.createElement('br');
      node.innerHTML = '';
      node.appendChild(tmpNode);
    },
    moveChild: function (src, tag, dir) {
      while (src.firstChild) {
        if (dir && tag.firstChild) {
          tag.insertBefore(src.lastChild, tag.firstChild);
        } else {
          tag.appendChild(src.firstChild);
        }
      }
    },
    hasNoAttributes: function (node) {
      return browser.ie ? /^<\w+\s*?>/.test(node.outerHTML) : node.attributes.length == 0;
    },
    isCustomeNode: function (node) {
      return node.nodeType == 1 && node.getAttribute('_ue_custom_node_');
    },
    isTagNode: function (node, tagNames) {
      return node.nodeType == 1 && new RegExp('\\b' + node.tagName + '\\b', 'i').test(tagNames);
    },
    filterNodeList: function (nodelist, filter, forAll) {
      var results = [];
      if (!utils.isFunction(filter)) {
        var str = filter;
        filter = function (n) {
          return utils.indexOf(utils.isArray(str) ? str : str.split(' '), n.tagName.toLowerCase()) != -1;
        };
      }
      utils.each(nodelist, function (n) {
        filter(n) && results.push(n);
      });
      return results.length == 0 ? null : results.length == 1 || !forAll ? results[0] : results;
    },
    isInNodeEndBoundary: function (rng, node) {
      var start = rng.startContainer;
      if (start.nodeType == 3 && rng.startOffset != start.nodeValue.length) {
        return 0;
      }
      if (start.nodeType == 1 && rng.startOffset != start.childNodes.length) {
        return 0;
      }
      while (start !== node) {
        if (start.nextSibling) {
          return 0;
        }
        start = start.parentNode;
      }
      return 1;
    },
    isBoundaryNode: function (node, dir) {
      var tmp;
      while (!domUtils.isBody(node)) {
        tmp = node;
        node = node.parentNode;
        if (tmp !== node[dir]) {
          return false;
        }
      }
      return true;
    },
    fillHtml: browser.ie11below ? '&nbsp;' : '<br/>',
    loadScript: function (url, cb) {
      var script;
      script = document.createElement('script');
      script.src = url;
      script.onload = function () {
        cb && cb({ isNew: true });
      };
      document.getElementsByTagName('head')[0].appendChild(script);
    },
  });
  var fillCharReg = new RegExp(domUtils.fillChar, 'g');
  (function () {
    var guid = 0,
      fillChar = domUtils.fillChar,
      fillData;
    function updateCollapse(range) {
      range.collapsed =
        range.startContainer &&
        range.endContainer &&
        range.startContainer === range.endContainer &&
        range.startOffset === range.endOffset;
    }
    function selectOneNode(rng) {
      return (
        !rng.collapsed &&
        rng.startContainer.nodeType === 1 &&
        rng.startContainer === rng.endContainer &&
        rng.endOffset - rng.startOffset === 1
      );
    }
    function setEndPoint(toStart, node, offset, range) {
      if (node.nodeType === 1 && (dtd.$empty[node.tagName] || dtd.$nonChild[node.tagName])) {
        offset = domUtils.getNodeIndex(node) + (toStart ? 0 : 1);
        node = node.parentNode;
      }
      if (toStart) {
        range.startContainer = node;
        range.startOffset = offset;
        if (!range.endContainer) {
          range.collapse(true);
        }
      } else {
        range.endContainer = node;
        range.endOffset = offset;
        if (!range.startContainer) {
          range.collapse(false);
        }
      }
      updateCollapse(range);
      return range;
    }
    function execContentsAction(range, action) {
      var start = range.startContainer,
        end = range.endContainer,
        startOffset = range.startOffset,
        endOffset = range.endOffset,
        doc = range.document,
        frag = doc.createDocumentFragment(),
        tmpStart,
        tmpEnd;
      if (start.nodeType == 1) {
        start = start.childNodes[startOffset] || (tmpStart = start.appendChild(doc.createTextNode('')));
      }
      if (end.nodeType == 1) {
        end = end.childNodes[endOffset] || (tmpEnd = end.appendChild(doc.createTextNode('')));
      }
      if (start === end && start.nodeType == 3) {
        frag.appendChild(doc.createTextNode(start.substringData(startOffset, endOffset - startOffset)));
        if (action) {
          start.deleteData(startOffset, endOffset - startOffset);
          range.collapse(true);
        }
        return frag;
      }
      var current,
        currentLevel,
        clone = frag,
        startParents = domUtils.findParents(start, true),
        endParents = domUtils.findParents(end, true);
      for (var i = 0; startParents[i] == endParents[i]; ) {
        i++;
      }
      for (var j = i, si; (si = startParents[j]); j++) {
        current = si.nextSibling;
        if (si == start) {
          if (!tmpStart) {
            if (range.startContainer.nodeType == 3) {
              clone.appendChild(doc.createTextNode(start.nodeValue.slice(startOffset)));
              if (action) {
                start.deleteData(startOffset, start.nodeValue.length - startOffset);
              }
            } else {
              clone.appendChild(!action ? start.cloneNode(true) : start);
            }
          }
        } else {
          currentLevel = si.cloneNode(false);
          clone.appendChild(currentLevel);
        }
        while (current) {
          if (current === end || current === endParents[j]) {
            break;
          }
          si = current.nextSibling;
          clone.appendChild(!action ? current.cloneNode(true) : current);
          current = si;
        }
        clone = currentLevel;
      }
      clone = frag;
      if (!startParents[i]) {
        clone.appendChild(startParents[i - 1].cloneNode(false));
        clone = clone.firstChild;
      }
      for (var j = i, ei; (ei = endParents[j]); j++) {
        current = ei.previousSibling;
        if (ei == end) {
          if (!tmpEnd && range.endContainer.nodeType == 3) {
            clone.appendChild(doc.createTextNode(end.substringData(0, endOffset)));
            if (action) {
              end.deleteData(0, endOffset);
            }
          }
        } else {
          currentLevel = ei.cloneNode(false);
          clone.appendChild(currentLevel);
        }
        if (j != i || !startParents[i]) {
          while (current) {
            if (current === start) {
              break;
            }
            ei = current.previousSibling;
            clone.insertBefore(!action ? current.cloneNode(true) : current, clone.firstChild);
            current = ei;
          }
        }
        clone = currentLevel;
      }
      if (action) {
        range
          .setStartBefore(!endParents[i] ? endParents[i - 1] : !startParents[i] ? startParents[i - 1] : endParents[i])
          .collapse(true);
      }
      tmpStart && domUtils.remove(tmpStart);
      tmpEnd && domUtils.remove(tmpEnd);
      return frag;
    }
    var Range = (dom.Range = function (document) {
      var me = this;
      me.startContainer = me.startOffset = me.endContainer = me.endOffset = null;
      me.document = document;
      me.collapsed = true;
    });
    function removeFillData(doc, excludeNode) {
      try {
        if (fillData && domUtils.inDoc(fillData, doc)) {
          if (!fillData.nodeValue.replace(fillCharReg, '').length) {
            var tmpNode = fillData.parentNode;
            domUtils.remove(fillData);
            while (
              tmpNode &&
              domUtils.isEmptyInlineElement(tmpNode) &&
              (browser.safari
                ? !(domUtils.getPosition(tmpNode, excludeNode) & domUtils.POSITION_CONTAINS)
                : !tmpNode.contains(excludeNode))
            ) {
              fillData = tmpNode.parentNode;
              domUtils.remove(tmpNode);
              tmpNode = fillData;
            }
          } else {
            fillData.nodeValue = fillData.nodeValue.replace(fillCharReg, '');
          }
        }
      } catch (e) {}
    }
    function mergeSibling(node, dir) {
      var tmpNode;
      node = node[dir];
      while (node && domUtils.isFillChar(node)) {
        tmpNode = node[dir];
        domUtils.remove(node);
        node = tmpNode;
      }
    }
    Range.prototype = {
      cloneContents: function () {
        return this.collapsed ? null : execContentsAction(this, 0);
      },
      deleteContents: function () {
        var txt;
        if (!this.collapsed) {
          execContentsAction(this, 1);
        }
        if (browser.webkit) {
          txt = this.startContainer;
          if (txt.nodeType == 3 && !txt.nodeValue.length) {
            this.setStartBefore(txt).collapse(true);
            domUtils.remove(txt);
          }
        }
        return this;
      },
      extractContents: function () {
        return this.collapsed ? null : execContentsAction(this, 2);
      },
      setStart: function (node, offset) {
        return setEndPoint(true, node, offset, this);
      },
      setEnd: function (node, offset) {
        return setEndPoint(false, node, offset, this);
      },
      setStartAfter: function (node) {
        return this.setStart(node.parentNode, domUtils.getNodeIndex(node) + 1);
      },
      setStartBefore: function (node) {
        return this.setStart(node.parentNode, domUtils.getNodeIndex(node));
      },
      setEndAfter: function (node) {
        return this.setEnd(node.parentNode, domUtils.getNodeIndex(node) + 1);
      },
      setEndBefore: function (node) {
        return this.setEnd(node.parentNode, domUtils.getNodeIndex(node));
      },
      setStartAtFirst: function (node) {
        return this.setStart(node, 0);
      },
      setStartAtLast: function (node) {
        return this.setStart(node, node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length);
      },
      setEndAtFirst: function (node) {
        return this.setEnd(node, 0);
      },
      setEndAtLast: function (node) {
        return this.setEnd(node, node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length);
      },
      selectNode: function (node) {
        return this.setStartBefore(node).setEndAfter(node);
      },
      selectNodeContents: function (node) {
        return this.setStart(node, 0).setEndAtLast(node);
      },
      cloneRange: function () {
        var me = this;
        return new Range(me.document).setStart(me.startContainer, me.startOffset).setEnd(me.endContainer, me.endOffset);
      },
      collapse: function (toStart) {
        var me = this;
        if (toStart) {
          me.endContainer = me.startContainer;
          me.endOffset = me.startOffset;
        } else {
          me.startContainer = me.endContainer;
          me.startOffset = me.endOffset;
        }
        me.collapsed = true;
        return me;
      },
      shrinkBoundary: function (ignoreEnd) {
        var me = this,
          child,
          collapsed = me.collapsed;
        function check(node) {
          return (
            node.nodeType == 1 &&
            !domUtils.isBookmarkNode(node) &&
            !dtd.$empty[node.tagName] &&
            !dtd.$nonChild[node.tagName]
          );
        }
        while (
          me.startContainer.nodeType == 1 &&
          (child = me.startContainer.childNodes[me.startOffset]) &&
          check(child)
        ) {
          me.setStart(child, 0);
        }
        if (collapsed) {
          return me.collapse(true);
        }
        if (!ignoreEnd) {
          while (
            me.endContainer.nodeType == 1 &&
            me.endOffset > 0 &&
            (child = me.endContainer.childNodes[me.endOffset - 1]) &&
            check(child)
          ) {
            me.setEnd(child, child.childNodes.length);
          }
        }
        return me;
      },
      getCommonAncestor: function (includeSelf, ignoreTextNode) {
        var me = this,
          start = me.startContainer,
          end = me.endContainer;
        if (start === end) {
          if (includeSelf && selectOneNode(this)) {
            start = start.childNodes[me.startOffset];
            if (start.nodeType == 1) return start;
          }
          return ignoreTextNode && start.nodeType == 3 ? start.parentNode : start;
        }
        return domUtils.getCommonAncestor(start, end);
      },
      trimBoundary: function (ignoreEnd) {
        this.txtToElmBoundary();
        var start = this.startContainer,
          offset = this.startOffset,
          collapsed = this.collapsed,
          end = this.endContainer;
        if (start.nodeType == 3) {
          if (offset == 0) {
            this.setStartBefore(start);
          } else {
            if (offset >= start.nodeValue.length) {
              this.setStartAfter(start);
            } else {
              var textNode = domUtils.split(start, offset);
              if (start === end) {
                this.setEnd(textNode, this.endOffset - offset);
              } else if (start.parentNode === end) {
                this.endOffset += 1;
              }
              this.setStartBefore(textNode);
            }
          }
          if (collapsed) {
            return this.collapse(true);
          }
        }
        if (!ignoreEnd) {
          offset = this.endOffset;
          end = this.endContainer;
          if (end.nodeType == 3) {
            if (offset == 0) {
              this.setEndBefore(end);
            } else {
              offset < end.nodeValue.length && domUtils.split(end, offset);
              this.setEndAfter(end);
            }
          }
        }
        return this;
      },
      txtToElmBoundary: function (ignoreCollapsed) {
        function adjust(r, c) {
          var container = r[c + 'Container'],
            offset = r[c + 'Offset'];
          if (container.nodeType == 3) {
            if (!offset) {
              r[
                'set' +
                  c.replace(/(\w)/, function (a) {
                    return a.toUpperCase();
                  }) +
                  'Before'
              ](container);
            } else if (offset >= container.nodeValue.length) {
              r[
                'set' +
                  c.replace(/(\w)/, function (a) {
                    return a.toUpperCase();
                  }) +
                  'After'
              ](container);
            }
          }
        }
        if (ignoreCollapsed || !this.collapsed) {
          adjust(this, 'start');
          adjust(this, 'end');
        }
        return this;
      },
      insertNode: function (node) {
        var first = node,
          length = 1;
        if (node.nodeType == 11) {
          first = node.firstChild;
          length = node.childNodes.length;
        }
        this.trimBoundary(true);
        var start = this.startContainer,
          offset = this.startOffset;
        var nextNode = start.childNodes[offset];
        if (nextNode) {
          start.insertBefore(node, nextNode);
        } else {
          start.appendChild(node);
        }
        if (first.parentNode === this.endContainer) {
          this.endOffset = this.endOffset + length;
        }
        return this.setStartBefore(first);
      },
      setCursor: function (toEnd, noFillData) {
        return this.collapse(!toEnd).select(noFillData);
      },
      createBookmark: function (serialize, same) {
        var endNode,
          startNode = this.document.createElement('span');
        startNode.style.cssText = 'display:none;line-height:0px;';
        startNode.appendChild(this.document.createTextNode('‍'));
        startNode.id = '_baidu_bookmark_start_' + (same ? '' : guid++);
        if (!this.collapsed) {
          endNode = startNode.cloneNode(true);
          endNode.id = '_baidu_bookmark_end_' + (same ? '' : guid++);
        }
        this.insertNode(startNode);
        if (endNode) {
          this.collapse().insertNode(endNode).setEndBefore(endNode);
        }
        this.setStartAfter(startNode);
        return {
          start: serialize ? startNode.id : startNode,
          end: endNode ? (serialize ? endNode.id : endNode) : null,
          id: serialize,
        };
      },
      moveToBookmark: function (bookmark) {
        var start = bookmark.id ? this.document.getElementById(bookmark.start) : bookmark.start,
          end = bookmark.end && bookmark.id ? this.document.getElementById(bookmark.end) : bookmark.end;
        this.setStartBefore(start);
        domUtils.remove(start);
        if (end) {
          this.setEndBefore(end);
          domUtils.remove(end);
        } else {
          this.collapse(true);
        }
        return this;
      },
      enlarge: function (toBlock, stopFn) {
        var isBody = domUtils.isBody,
          pre,
          node,
          tmp = this.document.createTextNode('');
        if (toBlock) {
          node = this.startContainer;
          if (node.nodeType == 1) {
            if (node.childNodes[this.startOffset]) {
              pre = node = node.childNodes[this.startOffset];
            } else {
              node.appendChild(tmp);
              pre = node = tmp;
            }
          } else {
            pre = node;
          }
          while (1) {
            if (domUtils.isBlockElm(node)) {
              node = pre;
              while ((pre = node.previousSibling) && !domUtils.isBlockElm(pre)) {
                node = pre;
              }
              this.setStartBefore(node);
              break;
            }
            pre = node;
            node = node.parentNode;
          }
          node = this.endContainer;
          if (node.nodeType == 1) {
            if ((pre = node.childNodes[this.endOffset])) {
              node.insertBefore(tmp, pre);
            } else {
              node.appendChild(tmp);
            }
            pre = node = tmp;
          } else {
            pre = node;
          }
          while (1) {
            if (domUtils.isBlockElm(node)) {
              node = pre;
              while ((pre = node.nextSibling) && !domUtils.isBlockElm(pre)) {
                node = pre;
              }
              this.setEndAfter(node);
              break;
            }
            pre = node;
            node = node.parentNode;
          }
          if (tmp.parentNode === this.endContainer) {
            this.endOffset--;
          }
          domUtils.remove(tmp);
        }
        if (!this.collapsed) {
          while (this.startOffset == 0) {
            if (stopFn && stopFn(this.startContainer)) {
              break;
            }
            if (isBody(this.startContainer)) {
              break;
            }
            this.setStartBefore(this.startContainer);
          }
          while (
            this.endOffset ==
            (this.endContainer.nodeType == 1 ? this.endContainer.childNodes.length : this.endContainer.nodeValue.length)
          ) {
            if (stopFn && stopFn(this.endContainer)) {
              break;
            }
            if (isBody(this.endContainer)) {
              break;
            }
            this.setEndAfter(this.endContainer);
          }
        }
        return this;
      },
      enlargeToBlockElm: function (ignoreEnd) {
        while (!domUtils.isBlockElm(this.startContainer)) {
          this.setStartBefore(this.startContainer);
        }
        if (!ignoreEnd) {
          while (!domUtils.isBlockElm(this.endContainer)) {
            this.setEndAfter(this.endContainer);
          }
        }
        return this;
      },
      adjustmentBoundary: function () {
        if (!this.collapsed) {
          while (
            !domUtils.isBody(this.startContainer) &&
            this.startOffset ==
              this.startContainer[this.startContainer.nodeType == 3 ? 'nodeValue' : 'childNodes'].length &&
            this.startContainer[this.startContainer.nodeType == 3 ? 'nodeValue' : 'childNodes'].length
          ) {
            this.setStartAfter(this.startContainer);
          }
          while (
            !domUtils.isBody(this.endContainer) &&
            !this.endOffset &&
            this.endContainer[this.endContainer.nodeType == 3 ? 'nodeValue' : 'childNodes'].length
          ) {
            this.setEndBefore(this.endContainer);
          }
        }
        return this;
      },
      applyInlineStyle: function (tagName, attrs, list) {
        if (this.collapsed) return this;
        this.trimBoundary()
          .enlarge(false, function (node) {
            return node.nodeType == 1 && domUtils.isBlockElm(node);
          })
          .adjustmentBoundary();
        var bookmark = this.createBookmark(),
          end = bookmark.end,
          filterFn = function (node) {
            return node.nodeType == 1 ? node.tagName.toLowerCase() != 'br' : !domUtils.isWhitespace(node);
          },
          current = domUtils.getNextDomNode(bookmark.start, false, filterFn),
          node,
          pre,
          range = this.cloneRange();
        while (current && domUtils.getPosition(current, end) & domUtils.POSITION_PRECEDING) {
          if (current.nodeType == 3 || dtd[tagName][current.tagName]) {
            range.setStartBefore(current);
            node = current;
            while (node && (node.nodeType == 3 || dtd[tagName][node.tagName]) && node !== end) {
              pre = node;
              node = domUtils.getNextDomNode(node, node.nodeType == 1, null, function (parent) {
                return dtd[tagName][parent.tagName];
              });
            }
            var frag = range.setEndAfter(pre).extractContents(),
              elm;
            if (list && list.length > 0) {
              var level, top;
              top = level = list[0].cloneNode(false);
              for (var i = 1, ci; (ci = list[i++]); ) {
                level.appendChild(ci.cloneNode(false));
                level = level.firstChild;
              }
              elm = level;
            } else {
              elm = range.document.createElement(tagName);
            }
            if (attrs) {
              domUtils.setAttributes(elm, attrs);
            }
            elm.appendChild(frag);
            if (elm.tagName == 'SPAN' && attrs && attrs.style) {
              utils.each(elm.getElementsByTagName('span'), function (s) {
                s.style.cssText = s.style.cssText + ';' + attrs.style;
              });
            }
            range.insertNode(list ? top : elm);
            var aNode;
            if (
              tagName == 'span' &&
              attrs.style &&
              /text\-decoration/.test(attrs.style) &&
              (aNode = domUtils.findParentByTagName(elm, 'a', true))
            ) {
              domUtils.setAttributes(aNode, attrs);
              domUtils.remove(elm, true);
              elm = aNode;
            } else {
              domUtils.mergeSibling(elm);
              domUtils.clearEmptySibling(elm);
            }
            domUtils.mergeChild(elm, attrs);
            current = domUtils.getNextDomNode(elm, false, filterFn);
            domUtils.mergeToParent(elm);
            if (node === end) {
              break;
            }
          } else {
            current = domUtils.getNextDomNode(current, true, filterFn);
          }
        }
        return this.moveToBookmark(bookmark);
      },
      removeInlineStyle: function (tagNames) {
        if (this.collapsed) return this;
        tagNames = utils.isArray(tagNames) ? tagNames : [tagNames];
        this.shrinkBoundary().adjustmentBoundary();
        var start = this.startContainer,
          end = this.endContainer;
        while (1) {
          if (start.nodeType == 1) {
            if (utils.indexOf(tagNames, start.tagName.toLowerCase()) > -1) {
              break;
            }
            if (start.tagName.toLowerCase() == 'body') {
              start = null;
              break;
            }
          }
          start = start.parentNode;
        }
        while (1) {
          if (end.nodeType == 1) {
            if (utils.indexOf(tagNames, end.tagName.toLowerCase()) > -1) {
              break;
            }
            if (end.tagName.toLowerCase() == 'body') {
              end = null;
              break;
            }
          }
          end = end.parentNode;
        }
        var bookmark = this.createBookmark(),
          frag,
          tmpRange;
        if (start) {
          tmpRange = this.cloneRange().setEndBefore(bookmark.start).setStartBefore(start);
          frag = tmpRange.extractContents();
          tmpRange.insertNode(frag);
          domUtils.clearEmptySibling(start, true);
          start.parentNode.insertBefore(bookmark.start, start);
        }
        if (end) {
          tmpRange = this.cloneRange().setStartAfter(bookmark.end).setEndAfter(end);
          frag = tmpRange.extractContents();
          tmpRange.insertNode(frag);
          domUtils.clearEmptySibling(end, false, true);
          end.parentNode.insertBefore(bookmark.end, end.nextSibling);
        }
        var current = domUtils.getNextDomNode(bookmark.start, false, function (node) {
            return node.nodeType == 1;
          }),
          next;
        while (current && current !== bookmark.end) {
          next = domUtils.getNextDomNode(current, true, function (node) {
            return node.nodeType == 1;
          });
          if (utils.indexOf(tagNames, current.tagName.toLowerCase()) > -1) {
            domUtils.remove(current, true);
          }
          current = next;
        }
        return this.moveToBookmark(bookmark);
      },
      getClosedNode: function () {
        var node;
        if (!this.collapsed) {
          var range = this.cloneRange().adjustmentBoundary().shrinkBoundary();
          if (selectOneNode(range)) {
            var child = range.startContainer.childNodes[range.startOffset];
            if (child && child.nodeType === 1 && (dtd.$empty[child.tagName] || dtd.$nonChild[child.tagName])) {
              node = child;
            }
          }
        }
        return node;
      },
      select: browser.ie
        ? function (noFillData, textRange) {
            var nativeRange;
            if (!this.collapsed) this.shrinkBoundary();
            var node = this.getClosedNode();
            if (node && !textRange) {
              try {
                nativeRange = this.document.body.createControlRange();
                nativeRange.addElement(node);
                nativeRange.select();
              } catch (e) {}
              return this;
            }
            var bookmark = this.createBookmark(),
              start = bookmark.start,
              end;
            nativeRange = this.document.body.createTextRange();
            nativeRange.moveToElementText(start);
            nativeRange.moveStart('character', 1);
            if (!this.collapsed) {
              var nativeRangeEnd = this.document.body.createTextRange();
              end = bookmark.end;
              nativeRangeEnd.moveToElementText(end);
              nativeRange.setEndPoint('EndToEnd', nativeRangeEnd);
            } else {
              if (!noFillData && this.startContainer.nodeType != 3) {
                var tmpText = this.document.createTextNode(fillChar),
                  tmp = this.document.createElement('span');
                tmp.appendChild(this.document.createTextNode(fillChar));
                start.parentNode.insertBefore(tmp, start);
                start.parentNode.insertBefore(tmpText, start);
                removeFillData(this.document, tmpText);
                fillData = tmpText;
                mergeSibling(tmp, 'previousSibling');
                mergeSibling(start, 'nextSibling');
                nativeRange.moveStart('character', -1);
                nativeRange.collapse(true);
              }
            }
            this.moveToBookmark(bookmark);
            tmp && domUtils.remove(tmp);
            try {
              nativeRange.select();
            } catch (e) {}
            return this;
          }
        : function (notInsertFillData) {
            function checkOffset(rng) {
              function check(node, offset, dir) {
                if (node.nodeType == 3 && node.nodeValue.length < offset) {
                  rng[dir + 'Offset'] = node.nodeValue.length;
                }
              }
              check(rng.startContainer, rng.startOffset, 'start');
              check(rng.endContainer, rng.endOffset, 'end');
            }
            var win = domUtils.getWindow(this.document),
              sel = win.getSelection(),
              txtNode;
            browser.gecko ? this.document.body.focus() : win.focus();
            if (sel) {
              sel.removeAllRanges();
              if (this.collapsed && !notInsertFillData) {
                var start = this.startContainer,
                  child = start;
                if (start.nodeType == 1) {
                  child = start.childNodes[this.startOffset];
                }
                if (
                  !(start.nodeType == 3 && this.startOffset) &&
                  (child
                    ? !child.previousSibling || child.previousSibling.nodeType != 3
                    : !start.lastChild || start.lastChild.nodeType != 3)
                ) {
                  txtNode = this.document.createTextNode(fillChar);
                  this.insertNode(txtNode);
                  removeFillData(this.document, txtNode);
                  mergeSibling(txtNode, 'previousSibling');
                  mergeSibling(txtNode, 'nextSibling');
                  fillData = txtNode;
                  this.setStart(txtNode, browser.webkit ? 1 : 0).collapse(true);
                }
              }
              var nativeRange = this.document.createRange();
              if (this.collapsed && browser.opera && this.startContainer.nodeType == 1) {
                var child = this.startContainer.childNodes[this.startOffset];
                if (!child) {
                  child = this.startContainer.lastChild;
                  if (child && domUtils.isBr(child)) {
                    this.setStartBefore(child).collapse(true);
                  }
                } else {
                  while (child && domUtils.isBlockElm(child)) {
                    if (child.nodeType == 1 && child.childNodes[0]) {
                      child = child.childNodes[0];
                    } else {
                      break;
                    }
                  }
                  child && this.setStartBefore(child).collapse(true);
                }
              }
              checkOffset(this);
              nativeRange.setStart(this.startContainer, this.startOffset);
              nativeRange.setEnd(this.endContainer, this.endOffset);
              sel.addRange(nativeRange);
            }
            return this;
          },
      scrollToView: function (win, offset) {
        win = win ? window : domUtils.getWindow(this.document);
        offset = offset || win.innerHeight - 100;
        var me = this,
          span = me.document.createElement('span');
        span.innerHTML = '&nbsp;';
        me.cloneRange().insertNode(span);
        domUtils.scrollToView(span, win, offset);
        domUtils.remove(span);
        return me;
      },
      inFillChar: function () {
        var start = this.startContainer;
        if (
          this.collapsed &&
          start.nodeType == 3 &&
          start.nodeValue.replace(new RegExp('^' + domUtils.fillChar), '').length + 1 == start.nodeValue.length
        ) {
          return true;
        }
        return false;
      },
      createAddress: function (ignoreEnd, ignoreTxt) {
        var addr = {},
          me = this;
        function getAddress(isStart) {
          var node = isStart ? me.startContainer : me.endContainer;
          var parents = domUtils.findParents(node, true, function (node) {
              return !domUtils.isBody(node);
            }),
            addrs = [];
          for (var i = 0, ci; (ci = parents[i++]); ) {
            addrs.push(domUtils.getNodeIndex(ci, ignoreTxt));
          }
          var firstIndex = 0;
          if (ignoreTxt) {
            if (node.nodeType == 3) {
              var tmpNode = node.previousSibling;
              while (tmpNode && tmpNode.nodeType == 3) {
                firstIndex += tmpNode.nodeValue.replace(fillCharReg, '').length;
                tmpNode = tmpNode.previousSibling;
              }
              firstIndex += isStart ? me.startOffset : me.endOffset;
            } else {
              node = node.childNodes[isStart ? me.startOffset : me.endOffset];
              if (node) {
                firstIndex = domUtils.getNodeIndex(node, ignoreTxt);
              } else {
                node = isStart ? me.startContainer : me.endContainer;
                var first = node.firstChild;
                while (first) {
                  if (domUtils.isFillChar(first)) {
                    first = first.nextSibling;
                    continue;
                  }
                  firstIndex++;
                  if (first.nodeType == 3) {
                    while (first && first.nodeType == 3) {
                      first = first.nextSibling;
                    }
                  } else {
                    first = first.nextSibling;
                  }
                }
              }
            }
          } else {
            firstIndex = isStart ? (domUtils.isFillChar(node) ? 0 : me.startOffset) : me.endOffset;
          }
          if (firstIndex < 0) {
            firstIndex = 0;
          }
          addrs.push(firstIndex);
          return addrs;
        }
        addr.startAddress = getAddress(true);
        if (!ignoreEnd) {
          addr.endAddress = me.collapsed ? [].concat(addr.startAddress) : getAddress();
        }
        return addr;
      },
      moveToAddress: function (addr, ignoreEnd) {
        var me = this;
        function getNode(address, isStart) {
          var tmpNode = me.document.body,
            parentNode,
            offset;
          for (var i = 0, ci, l = address.length; i < l; i++) {
            ci = address[i];
            parentNode = tmpNode;
            tmpNode = tmpNode.childNodes[ci];
            if (!tmpNode) {
              offset = ci;
              break;
            }
          }
          if (isStart) {
            if (tmpNode) {
              me.setStartBefore(tmpNode);
            } else {
              me.setStart(parentNode, offset);
            }
          } else {
            if (tmpNode) {
              me.setEndBefore(tmpNode);
            } else {
              me.setEnd(parentNode, offset);
            }
          }
        }
        getNode(addr.startAddress, true);
        !ignoreEnd && addr.endAddress && getNode(addr.endAddress);
        return me;
      },
      equals: function (rng) {
        for (var p in this) {
          if (this.hasOwnProperty(p)) {
            if (this[p] !== rng[p]) return false;
          }
        }
        return true;
      },
      traversal: function (doFn, filterFn) {
        if (this.collapsed) return this;
        var bookmark = this.createBookmark(),
          end = bookmark.end,
          current = domUtils.getNextDomNode(bookmark.start, false, filterFn);
        while (current && current !== end && domUtils.getPosition(current, end) & domUtils.POSITION_PRECEDING) {
          var tmpNode = domUtils.getNextDomNode(current, false, filterFn);
          doFn(current);
          current = tmpNode;
        }
        return this.moveToBookmark(bookmark);
      },
    };
  })();
  (function () {
    function getBoundaryInformation(range, start) {
      var getIndex = domUtils.getNodeIndex;
      range = range.duplicate();
      range.collapse(start);
      var parent = range.parentElement();
      if (!parent.hasChildNodes()) {
        return { container: parent, offset: 0 };
      }
      var siblings = parent.children,
        child,
        testRange = range.duplicate(),
        startIndex = 0,
        endIndex = siblings.length - 1,
        index = -1,
        distance;
      while (startIndex <= endIndex) {
        index = Math.floor((startIndex + endIndex) / 2);
        child = siblings[index];
        testRange.moveToElementText(child);
        var position = testRange.compareEndPoints('StartToStart', range);
        if (position > 0) {
          endIndex = index - 1;
        } else if (position < 0) {
          startIndex = index + 1;
        } else {
          return { container: parent, offset: getIndex(child) };
        }
      }
      if (index == -1) {
        testRange.moveToElementText(parent);
        testRange.setEndPoint('StartToStart', range);
        distance = testRange.text.replace(/(\r\n|\r)/g, '\n').length;
        siblings = parent.childNodes;
        if (!distance) {
          child = siblings[siblings.length - 1];
          return { container: child, offset: child.nodeValue.length };
        }
        var i = siblings.length;
        while (distance > 0) {
          distance -= siblings[--i].nodeValue.length;
        }
        return { container: siblings[i], offset: -distance };
      }
      testRange.collapse(position > 0);
      testRange.setEndPoint(position > 0 ? 'StartToStart' : 'EndToStart', range);
      distance = testRange.text.replace(/(\r\n|\r)/g, '\n').length;
      if (!distance) {
        return dtd.$empty[child.tagName] || dtd.$nonChild[child.tagName]
          ? { container: parent, offset: getIndex(child) + (position > 0 ? 0 : 1) }
          : { container: child, offset: position > 0 ? 0 : child.childNodes.length };
      }
      while (distance > 0) {
        try {
          var pre = child;
          child = child[position > 0 ? 'previousSibling' : 'nextSibling'];
          distance -= child.nodeValue.length;
        } catch (e) {
          return { container: parent, offset: getIndex(pre) };
        }
      }
      return { container: child, offset: position > 0 ? -distance : child.nodeValue.length + distance };
    }
    function transformIERangeToRange(ieRange, range) {
      if (ieRange.item) {
        range.selectNode(ieRange.item(0));
      } else {
        var bi = getBoundaryInformation(ieRange, true);
        range.setStart(bi.container, bi.offset);
        if (ieRange.compareEndPoints('StartToEnd', ieRange) != 0) {
          bi = getBoundaryInformation(ieRange, false);
          range.setEnd(bi.container, bi.offset);
        }
      }
      return range;
    }
    function _getIERange(sel) {
      var ieRange;
      try {
        ieRange = sel.getNative().createRange();
      } catch (e) {
        return null;
      }
      var el = ieRange.item ? ieRange.item(0) : ieRange.parentElement();
      if ((el.ownerDocument || el) === sel.document) {
        return ieRange;
      }
      return null;
    }
    var Selection = (dom.Selection = function (doc) {
      var me = this,
        iframe;
      me.document = doc;
      if (browser.ie9below) {
        iframe = domUtils.getWindow(doc).frameElement;
        domUtils.on(iframe, 'beforedeactivate', function () {
          me._bakIERange = me.getIERange();
        });
        domUtils.on(iframe, 'activate', function () {
          try {
            if (!_getIERange(me) && me._bakIERange) {
              me._bakIERange.select();
            }
          } catch (ex) {}
          me._bakIERange = null;
        });
      }
      iframe = doc = null;
    });
    Selection.prototype = {
      rangeInBody: function (rng, txtRange) {
        var node = browser.ie9below || txtRange ? (rng.item ? rng.item() : rng.parentElement()) : rng.startContainer;
        return node === this.document.body || domUtils.inDoc(node, this.document);
      },
      getNative: function () {
        var doc = this.document;
        try {
          return !doc ? null : browser.ie9below ? doc.selection : domUtils.getWindow(doc).getSelection();
        } catch (e) {
          return null;
        }
      },
      getIERange: function () {
        var ieRange = _getIERange(this);
        if (!ieRange) {
          if (this._bakIERange) {
            return this._bakIERange;
          }
        }
        return ieRange;
      },
      cache: function () {
        this.clear();
        this._cachedRange = this.getRange();
        this._cachedStartElement = this.getStart();
        this._cachedStartElementPath = this.getStartElementPath();
      },
      getStartElementPath: function () {
        if (this._cachedStartElementPath) {
          return this._cachedStartElementPath;
        }
        var start = this.getStart();
        if (start) {
          return domUtils.findParents(start, true, null, true);
        }
        return [];
      },
      clear: function () {
        this._cachedStartElementPath = this._cachedRange = this._cachedStartElement = null;
      },
      isFocus: function () {
        try {
          if (browser.ie9below) {
            var nativeRange = _getIERange(this);
            return !!(nativeRange && this.rangeInBody(nativeRange));
          } else {
            return !!this.getNative().rangeCount;
          }
        } catch (e) {
          return false;
        }
      },
      getRange: function () {
        var me = this;
        function optimze(range) {
          var child = me.document.body.firstChild,
            collapsed = range.collapsed;
          while (child && child.firstChild) {
            range.setStart(child, 0);
            child = child.firstChild;
          }
          if (!range.startContainer) {
            range.setStart(me.document.body, 0);
          }
          if (collapsed) {
            range.collapse(true);
          }
        }
        if (me._cachedRange != null) {
          return this._cachedRange;
        }
        var range = new baidu.editor.dom.Range(me.document);
        if (browser.ie9below) {
          var nativeRange = me.getIERange();
          if (nativeRange) {
            try {
              transformIERangeToRange(nativeRange, range);
            } catch (e) {
              optimze(range);
            }
          } else {
            optimze(range);
          }
        } else {
          var sel = me.getNative();
          if (sel && sel.rangeCount) {
            var firstRange = sel.getRangeAt(0);
            var lastRange = sel.getRangeAt(sel.rangeCount - 1);
            range
              .setStart(firstRange.startContainer, firstRange.startOffset)
              .setEnd(lastRange.endContainer, lastRange.endOffset);
            if (range.collapsed && domUtils.isBody(range.startContainer) && !range.startOffset) {
              optimze(range);
            }
          } else {
            if (this._bakRange && domUtils.inDoc(this._bakRange.startContainer, this.document)) {
              return this._bakRange;
            }
            optimze(range);
          }
        }
        return (this._bakRange = range);
      },
      getStart: function () {
        if (this._cachedStartElement) {
          return this._cachedStartElement;
        }
        var range = browser.ie9below ? this.getIERange() : this.getRange(),
          tmpRange,
          start,
          tmp,
          parent;
        if (browser.ie9below) {
          if (!range) {
            return this.document.body.firstChild;
          }
          if (range.item) {
            return range.item(0);
          }
          tmpRange = range.duplicate();
          tmpRange.text.length > 0 && tmpRange.moveStart('character', 1);
          tmpRange.collapse(1);
          start = tmpRange.parentElement();
          parent = tmp = range.parentElement();
          while ((tmp = tmp.parentNode)) {
            if (tmp == start) {
              start = parent;
              break;
            }
          }
        } else {
          range.shrinkBoundary();
          start = range.startContainer;
          if (start.nodeType == 1 && start.hasChildNodes()) {
            start = start.childNodes[Math.min(start.childNodes.length - 1, range.startOffset)];
          }
          if (start.nodeType == 3) {
            return start.parentNode;
          }
        }
        return start;
      },
      getText: function () {
        var nativeSel, nativeRange;
        if (this.isFocus() && (nativeSel = this.getNative())) {
          nativeRange = browser.ie9below ? nativeSel.createRange() : nativeSel.getRangeAt(0);
          return browser.ie9below ? nativeRange.text : nativeRange.toString();
        }
        return '';
      },
      clearRange: function () {
        this.getNative()[browser.ie9below ? 'empty' : 'removeAllRanges']();
      },
    };
  })();
  (function () {
    var uid = 0,
      _selectionChangeTimer;
    function setValue(form, editor) {
      if (!editor.options.textarea) {
        return;
      }
      var textarea;
      textarea = editor.textarea;
      if (!textarea) {
        textarea = domUtils.getElementsByTagName(form, 'textarea', function (node) {
          return node.id === 'ueditor_textarea_' + editor.options.textarea;
        })[0];
      }
      if (!textarea) {
        textarea = domUtils.getElementsByTagName(form, 'textarea', function (node) {
          return node.name === editor.options.textarea;
        })[0];
      }
      if (!textarea) {
        form.appendChild(
          (textarea = domUtils.createElement(document, 'textarea', {
            name: editor.options.textarea,
            id: 'ueditor_textarea_' + editor.options.textarea,
            style: 'display:none',
          })),
        );
      }
      if (textarea && !editor.textarea) {
        editor.textarea = textarea;
      }
      !textarea.getAttribute('name') && textarea.setAttribute('name', editor.options.textarea);
      textarea.value = editor.hasContents()
        ? editor.options.allHtmlEnabled
          ? editor.getAllHtml()
          : editor.getContent(null, null, true)
        : '';
    }
    function loadPlugins(me) {
      for (var pi in UE.plugins) {
        UE.plugins[pi].call(me);
      }
    }
    function checkCurLang(I18N) {
      for (var lang in I18N) {
        return lang;
      }
    }
    function langReadied(me) {
      me.langIsReady = true;
      me.fireEvent('langReady');
    }
    var Editor = (UE.Editor = function (options) {
      var me = this;
      me.uid = uid++;
      EventBase.call(me);
      me.commands = {};
      me.options = utils.extend(utils.clone(options || {}), UEDITOR_CONFIG, true);
      me.shortcutkeys = {};
      me.inputRules = [];
      me.outputRules = [];
      me.setOpt(Editor.defaultOptions(me));
      me.loadServerConfig();
      if (!utils.isEmptyObject(UE.I18N)) {
        me.options.lang = checkCurLang(UE.I18N);
        UE.plugin.load(me);
        langReadied(me);
      } else {
        utils.loadFile(
          document,
          {
            src: me.options.langPath + me.options.lang + '/' + me.options.lang + '.js?58c38108',
            tag: 'script',
            type: 'text/javascript',
            defer: 'defer',
          },
          function () {
            UE.plugin.load(me);
            langReadied(me);
          },
        );
      }
      UE.instants['ueditorInstant' + me.uid] = me;
    });
    Editor.prototype = {
      registerCommand: function (name, obj) {
        this.commands[name] = obj;
      },
      ready: function (fn) {
        var me = this;
        if (fn) {
          me.isReady ? fn.apply(me) : me.addListener('ready', fn);
        }
      },
      setOpt: function (key, val) {
        var obj = {};
        if (utils.isString(key)) {
          obj[key] = val;
        } else {
          obj = key;
        }
        utils.extend(this.options, obj, true);
      },
      getOpt: function (key) {
        return this.options[key];
      },
      destroy: function () {
        var me = this;
        me.fireEvent('destroy');
        var container = me.container.parentNode;
        var textarea = me.textarea;
        if (!textarea) {
          textarea = document.createElement('textarea');
          container.parentNode.insertBefore(textarea, container);
        } else {
          textarea.style.display = '';
        }
        textarea.style.width = me.iframe.offsetWidth + 'px';
        textarea.style.height = me.iframe.offsetHeight + 'px';
        textarea.value = me.getContent();
        textarea.id = me.key;
        container.innerHTML = '';
        domUtils.remove(container);
        var key = me.key;
        for (var p in me) {
          if (me.hasOwnProperty(p)) {
            delete this[p];
          }
        }
        UE.delEditor(key);
      },
      render: function (container) {
        var me = this,
          options = me.options,
          getStyleValue = function (attr) {
            return parseInt(domUtils.getComputedStyle(container, attr));
          };
        if (utils.isString(container)) {
          container = document.getElementById(container);
        }
        if (container) {
          if (options.initialFrameWidth) {
            options.minFrameWidth = options.initialFrameWidth;
          } else {
            options.minFrameWidth = options.initialFrameWidth = container.offsetWidth;
          }
          if (options.initialFrameHeight) {
            options.minFrameHeight = options.initialFrameHeight;
          } else {
            options.initialFrameHeight = options.minFrameHeight = container.offsetHeight;
          }
          container.style.width = /%$/.test(options.initialFrameWidth)
            ? '100%'
            : options.initialFrameWidth - getStyleValue('padding-left') - getStyleValue('padding-right') + 'px';
          container.style.height = /%$/.test(options.initialFrameHeight)
            ? '100%'
            : options.initialFrameHeight - getStyleValue('padding-top') - getStyleValue('padding-bottom') + 'px';
          container.style.zIndex = options.zIndex;
          var additionCssHtml = [];
          for (var i in options.iframeCssUrlsAddition) {
            additionCssHtml.push(
              "<link rel='stylesheet' type='text/css' href='" + utils.unhtml(options.iframeCssUrlsAddition[i]) + "'/>",
            );
          }
          var html =
            (ie && browser.version < 9 ? '' : '<!DOCTYPE html>') +
            "<html xmlns='http://www.w3.org/1999/xhtml' class='view' >" +
            '<head>' +
            "<style type='text/css'>" +
            '.view{padding:0;word-wrap:break-word;cursor:text;height:90%;}\n' +
            'body{margin:8px;font-family:sans-serif;font-size:16px;}' +
            'img{max-width:100%;}' +
            'p{margin:5px 0;}</style>' +
            (options.iframeCssUrl
              ? "<link rel='stylesheet' type='text/css' href='" + utils.unhtml(options.iframeCssUrl) + "'/>"
              : '') +
            (options.initialStyle ? '<style>' + options.initialStyle + '</style>' : '') +
            additionCssHtml.join('') +
            '</head>' +
            "<body class='view' ></body>" +
            "<script type='text/javascript' " +
            (ie ? "defer='defer'" : '') +
            " id='_initialScript'>" +
            "setTimeout(function(){editor = window.parent.UE.instants['ueditorInstant" +
            me.uid +
            "'];editor._setup(document);},0);" +
            "var _tmpScript = document.getElementById('_initialScript');_tmpScript.parentNode.removeChild(_tmpScript);" +
            '<\/script>' +
            (options.iframeJsUrl
              ? "<script type='text/javascript' src='" + utils.unhtml(options.iframeJsUrl) + "'><\/script>"
              : '') +
            '</html>';
          container.appendChild(
            domUtils.createElement(document, 'iframe', {
              id: 'ueditor_' + me.uid,
              width: '100%',
              height: '100%',
              frameborder: '0',
              src:
                'javascript:void(function(){document.open();' +
                (options.customDomain && document.domain != location.hostname
                  ? 'document.domain="' + document.domain + '";'
                  : '') +
                'document.write("' +
                html +
                '");document.close();}())',
            }),
          );
          container.style.overflow = 'hidden';
          setTimeout(function () {
            if (/%$/.test(options.initialFrameWidth)) {
              options.minFrameWidth = options.initialFrameWidth = container.offsetWidth;
            }
            if (/%$/.test(options.initialFrameHeight)) {
              options.minFrameHeight = options.initialFrameHeight = container.offsetHeight;
              container.style.height = options.initialFrameHeight + 'px';
            }
          });
        }
      },
      _setup: function (doc) {
        var me = this,
          options = me.options;
        if (ie) {
          doc.body.disabled = true;
          doc.body.contentEditable = true;
          doc.body.disabled = false;
        } else {
          doc.body.contentEditable = true;
        }
        doc.body.spellcheck = false;
        me.document = doc;
        me.window = doc.defaultView || doc.parentWindow;
        me.iframe = me.window.frameElement;
        me.body = doc.body;
        me.selection = new dom.Selection(doc);
        var geckoSel;
        if (browser.gecko && (geckoSel = this.selection.getNative())) {
          geckoSel.removeAllRanges();
        }
        this._initEvents();
        for (var form = this.iframe.parentNode; !domUtils.isBody(form); form = form.parentNode) {
          if (form.tagName === 'FORM') {
            me.form = form;
            if (me.options.autoSyncData) {
              domUtils.on(me.window, 'blur', function () {
                setValue(form, me);
              });
              domUtils.on(form, 'submit', function () {
                me.fireEvent('beforesubmit');
              });
            } else {
              domUtils.on(form, 'submit', function () {
                setValue(this, me);
                me.fireEvent('beforesubmit');
              });
            }
            break;
          }
        }
        if (options.initialContent) {
          if (options.autoClearinitialContent) {
            var oldExecCommand = me.execCommand;
            me.execCommand = function () {
              me.fireEvent('firstBeforeExecCommand');
              return oldExecCommand.apply(me, arguments);
            };
            this._setDefaultContent(options.initialContent);
          } else this.setContent(options.initialContent, false, true);
        }
        if (domUtils.isEmptyNode(me.body)) {
          me.body.innerHTML = '<p>' + (browser.ie ? '' : '<br/>') + '</p>';
        }
        if (options.focus) {
          setTimeout(function () {
            me.focus(me.options.focusInEnd);
            !me.options.autoClearinitialContent && me._selectionChange();
          }, 0);
        }
        if (!me.container) {
          me.container = this.iframe.parentNode;
        }
        if (options.fullscreen && me.ui) {
          me.ui.setFullScreen(true);
        }
        try {
          me.document.execCommand('2D-position', false, false);
        } catch (e) {}
        try {
          me.document.execCommand('enableInlineTableEditing', false, false);
        } catch (e) {}
        try {
          me.document.execCommand('enableObjectResizing', false, false);
        } catch (e) {}
        me._bindshortcutKeys();
        me.isReady = 1;
        me.fireEvent('ready');
        options.onready && options.onready.call(me);
        if (!browser.ie9below) {
          domUtils.on(me.window, ['blur', 'focus'], function (e) {
            if (e.type == 'blur') {
              me._bakRange = me.selection.getRange();
              try {
                me._bakNativeRange = me.selection.getNative().getRangeAt(0);
                me.selection.getNative().removeAllRanges();
              } catch (e) {
                me._bakNativeRange = null;
              }
            } else {
              try {
                me._bakRange && me._bakRange.select();
              } catch (e) {}
            }
          });
        }
        if (browser.gecko && browser.version <= 10902) {
          me.body.contentEditable = false;
          setTimeout(function () {
            me.body.contentEditable = true;
          }, 100);
          setInterval(function () {
            me.body.style.height = me.iframe.offsetHeight - 20 + 'px';
          }, 100);
        }
        !options.isShow && me.setHide();
        options.readonly && me.setDisabled();
      },
      sync: function (formId) {
        var me = this,
          form = formId
            ? document.getElementById(formId)
            : domUtils.findParent(
                me.iframe.parentNode,
                function (node) {
                  return node.tagName === 'FORM';
                },
                true,
              );
        form && setValue(form, me);
      },
      syncCommandState: function () {
        this.fireEvent('selectionchange');
      },
      setWidth: function (width) {
        if (width !== parseInt(this.iframe.parentNode.parentNode.style.width)) {
          this.iframe.parentNode.parentNode.style.width = width + 'px';
        }
      },
      setHeight: function (height, notSetHeight) {
        if (height !== parseInt(this.iframe.parentNode.style.height)) {
          this.iframe.parentNode.style.height = height + 'px';
        }
        !notSetHeight && (this.options.minFrameHeight = this.options.initialFrameHeight = height);
        this.body.style.height = height + 'px';
        !notSetHeight && this.trigger('setHeight');
      },
      addshortcutkey: function (cmd, keys) {
        var obj = {};
        if (keys) {
          obj[cmd] = keys;
        } else {
          obj = cmd;
        }
        utils.extend(this.shortcutkeys, obj);
      },
      _bindshortcutKeys: function () {
        var me = this,
          shortcutkeys = this.shortcutkeys;
        me.addListener('keydown', function (type, e) {
          var keyCode = e.keyCode || e.which;
          for (var i in shortcutkeys) {
            var tmp = shortcutkeys[i].split(',');
            for (var t = 0, ti; (ti = tmp[t++]); ) {
              ti = ti.split(':');
              var key = ti[0],
                param = ti[1];
              if (/^(ctrl)(\+shift)?\+(\d+)$/.test(key.toLowerCase()) || /^(\d+)$/.test(key)) {
                if (
                  ((RegExp.$1 == 'ctrl' ? e.ctrlKey || e.metaKey : 0) &&
                    (RegExp.$2 != '' ? e[RegExp.$2.slice(1) + 'Key'] : 1) &&
                    keyCode == RegExp.$3) ||
                  keyCode == RegExp.$1
                ) {
                  if (me.queryCommandState(i, param) != -1) me.execCommand(i, param);
                  domUtils.preventDefault(e);
                }
              }
            }
          }
          var code = e.code;
          if (code) {
            if (code === 'Backspace') {
              if (e.target) {
                if (e.target.tagName === 'VIDEO') {
                  e.target.remove();
                }
              }
            }
          }
        });
      },
      getContent: function (cmd, fn, notSetCursor, ignoreBlank, formatter) {
        var me = this;
        if (cmd && utils.isFunction(cmd)) {
          fn = cmd;
          cmd = '';
        }
        if (fn ? !fn() : !this.hasContents()) {
          return '';
        }
        me.fireEvent('beforegetcontent');
        var root = UE.htmlparser(me.body.innerHTML, ignoreBlank);
        me.filterOutputRule(root);
        me.fireEvent('aftergetcontent', cmd, root);
        return root.toHtml(formatter);
      },
      getAllHtml: function () {
        var me = this,
          headHtml = [],
          html = '';
        me.fireEvent('getAllHtml', headHtml);
        if (browser.ie && browser.version > 8) {
          var headHtmlForIE9 = '';
          utils.each(me.document.styleSheets, function (si) {
            headHtmlForIE9 += si.href
              ? '<link rel="stylesheet" type="text/css" href="' + si.href + '" />'
              : '<style>' + si.cssText + '</style>';
          });
          utils.each(me.document.getElementsByTagName('script'), function (si) {
            headHtmlForIE9 += si.outerHTML;
          });
        }
        return (
          '<html><head>' +
          (me.options.charset
            ? '<meta http-equiv="Content-Type" content="text/html; charset=' + me.options.charset + '"/>'
            : '') +
          (headHtmlForIE9 || me.document.getElementsByTagName('head')[0].innerHTML) +
          headHtml.join('\n') +
          '</head>' +
          '<body ' +
          (ie && browser.version < 9 ? 'class="view"' : '') +
          '>' +
          me.getContent(null, null, true) +
          '</body></html>'
        );
      },
      getPlainTxt: function () {
        var reg = new RegExp(domUtils.fillChar, 'g'),
          html = this.body.innerHTML.replace(/[\n\r]/g, '');
        html = html
          .replace(/<(p|div)[^>]*>(<br\/?>|&nbsp;)<\/\1>/gi, '\n')
          .replace(/<br\/?>/gi, '\n')
          .replace(/<[^>/]+>/g, '')
          .replace(/(\n)?<\/([^>]+)>/g, function (a, b, c) {
            return dtd.$block[c] ? '\n' : b ? b : '';
          });
        return html
          .replace(reg, '')
          .replace(/\u00a0/g, ' ')
          .replace(/&nbsp;/g, ' ');
      },
      getContentTxt: function () {
        var reg = new RegExp(domUtils.fillChar, 'g');
        return this.body[browser.ie ? 'innerText' : 'textContent'].replace(reg, '').replace(/\u00a0/g, ' ');
      },
      setContent: function (html, isAppendTo, notFireSelectionchange) {
        var me = this;
        me.fireEvent('beforesetcontent', html);
        var root = UE.htmlparser(html);
        me.filterInputRule(root);
        html = root.toHtml();
        me.body.innerHTML = (isAppendTo ? me.body.innerHTML : '') + html;
        function isCdataDiv(node) {
          return node.tagName == 'DIV' && node.getAttribute('cdata_tag');
        }
        if (me.options.enterTag == 'p') {
          var child = this.body.firstChild,
            tmpNode;
          if (
            !child ||
            (child.nodeType == 1 &&
              (dtd.$cdata[child.tagName] || isCdataDiv(child) || domUtils.isCustomeNode(child)) &&
              child === this.body.lastChild)
          ) {
            this.body.innerHTML = '<p>' + (browser.ie ? '&nbsp;' : '<br/>') + '</p>' + this.body.innerHTML;
          } else {
            var p = me.document.createElement('p');
            while (child) {
              while (
                child &&
                (child.nodeType == 3 || (child.nodeType == 1 && dtd.p[child.tagName] && !dtd.$cdata[child.tagName]))
              ) {
                tmpNode = child.nextSibling;
                p.appendChild(child);
                child = tmpNode;
              }
              if (p.firstChild) {
                if (!child) {
                  me.body.appendChild(p);
                  break;
                } else {
                  child.parentNode.insertBefore(p, child);
                  p = me.document.createElement('p');
                }
              }
              child = child.nextSibling;
            }
          }
        }
        me.fireEvent('aftersetcontent');
        me.fireEvent('contentchange');
        !notFireSelectionchange && me._selectionChange();
        me._bakRange = me._bakIERange = me._bakNativeRange = null;
        var geckoSel;
        if (browser.gecko && (geckoSel = this.selection.getNative())) {
          geckoSel.removeAllRanges();
        }
        if (me.options.autoSyncData) {
          me.form && setValue(me.form, me);
        }
      },
      focus: function (toEnd) {
        try {
          var me = this,
            rng = me.selection.getRange();
          if (toEnd) {
            var node = me.body.lastChild;
            if (node && node.nodeType == 1 && !dtd.$empty[node.tagName]) {
              if (domUtils.isEmptyBlock(node)) {
                rng.setStartAtFirst(node);
              } else {
                rng.setStartAtLast(node);
              }
              rng.collapse(true);
            }
            rng.setCursor(true);
          } else {
            if (!rng.collapsed && domUtils.isBody(rng.startContainer) && rng.startOffset == 0) {
              var node = me.body.firstChild;
              if (node && node.nodeType == 1 && !dtd.$empty[node.tagName]) {
                rng.setStartAtFirst(node).collapse(true);
              }
            }
            rng.select(true);
          }
          this.fireEvent('focus selectionchange');
        } catch (e) {}
      },
      isFocus: function () {
        return this.selection.isFocus();
      },
      blur: function () {
        var sel = this.selection.getNative();
        if (sel.empty && browser.ie) {
          var nativeRng = document.body.createTextRange();
          nativeRng.moveToElementText(document.body);
          nativeRng.collapse(true);
          nativeRng.select();
          sel.empty();
        } else {
          sel.removeAllRanges();
        }
      },
      _initEvents: function () {
        var me = this,
          doc = me.document,
          win = me.window;
        me._proxyDomEvent = utils.bind(me._proxyDomEvent, me);
        domUtils.on(
          doc,
          [
            'click',
            'contextmenu',
            'mousedown',
            'keydown',
            'keyup',
            'keypress',
            'mouseup',
            'mouseover',
            'mouseout',
            'selectstart',
          ],
          me._proxyDomEvent,
        );
        domUtils.on(win, ['focus', 'blur'], me._proxyDomEvent);
        domUtils.on(me.body, 'drop', function (e) {
          if (browser.gecko && e.stopPropagation) {
            e.stopPropagation();
          }
          me.fireEvent('contentchange');
        });
        domUtils.on(me.body, 'dblclick', function (e) {
          try {
            var node = me.body.lastChild;
            if (!node) {
              return;
            }
            var rect = node.getBoundingClientRect();
            if (e.clientY > rect.top + rect.height) {
              var p = document.createElement('p');
              p.innerHTML = '<br />';
              me.body.appendChild(p);
              setTimeout(function () {
                me.focus(true);
              }, 100);
            }
          } catch (e) {
            console.error('auto insert p at end', e);
          }
        });
        domUtils.on(doc, ['mouseup', 'keydown'], function (evt) {
          if (evt.type === 'keydown' && (evt.ctrlKey || evt.metaKey || evt.shiftKey || evt.altKey)) {
            return;
          }
          if (evt.button === 2) return;
          me._selectionChange(250, evt);
        });
      },
      _proxyDomEvent: function (evt) {
        if (this.fireEvent('before' + evt.type.replace(/^on/, '').toLowerCase()) === false) {
          return false;
        }
        if (this.fireEvent(evt.type.replace(/^on/, ''), evt) === false) {
          return false;
        }
        return this.fireEvent('after' + evt.type.replace(/^on/, '').toLowerCase());
      },
      _selectionChange: function (delay, evt) {
        var me = this;
        var hackForMouseUp = false;
        var mouseX, mouseY;
        if (browser.ie && browser.version < 9 && evt && evt.type == 'mouseup') {
          var range = this.selection.getRange();
          if (!range.collapsed) {
            hackForMouseUp = true;
            mouseX = evt.clientX;
            mouseY = evt.clientY;
          }
        }
        clearTimeout(_selectionChangeTimer);
        _selectionChangeTimer = setTimeout(function () {
          if (!me.selection || !me.selection.getNative()) {
            return;
          }
          var ieRange;
          if (hackForMouseUp && me.selection.getNative().type == 'None') {
            ieRange = me.document.body.createTextRange();
            try {
              ieRange.moveToPoint(mouseX, mouseY);
            } catch (ex) {
              ieRange = null;
            }
          }
          var bakGetIERange;
          if (ieRange) {
            bakGetIERange = me.selection.getIERange;
            me.selection.getIERange = function () {
              return ieRange;
            };
          }
          me.selection.cache();
          if (bakGetIERange) {
            me.selection.getIERange = bakGetIERange;
          }
          if (me.selection._cachedRange && me.selection._cachedStartElement) {
            me.fireEvent('beforeselectionchange');
            me.fireEvent('selectionchange', !!evt);
            me.fireEvent('afterselectionchange');
            me.selection.clear();
          }
        }, delay || 50);
      },
      _callCmdFn: function (fnName, args) {
        var cmdName = args[0].toLowerCase(),
          cmd,
          cmdFn;
        cmd = this.commands[cmdName] || UE.commands[cmdName];
        cmdFn = cmd && cmd[fnName];
        if ((!cmd || !cmdFn) && fnName == 'queryCommandState') {
          return 0;
        } else if (cmdFn) {
          return cmdFn.apply(this, args);
        }
      },
      execCommand: function (cmdName) {
        cmdName = cmdName.toLowerCase();
        var me = this,
          result,
          cmd = me.commands[cmdName] || UE.commands[cmdName];
        if (!cmd || !cmd.execCommand) {
          return null;
        }
        if (!cmd.notNeedUndo && !me.__hasEnterExecCommand) {
          me.__hasEnterExecCommand = true;
          if (me.queryCommandState.apply(me, arguments) != -1) {
            me.fireEvent('saveScene');
            me.fireEvent.apply(me, ['beforeexeccommand', cmdName].concat(arguments));
            result = this._callCmdFn('execCommand', arguments);
            me.fireEvent.apply(me, ['afterexeccommand', cmdName].concat(arguments));
            me.fireEvent('saveScene');
          }
          me.__hasEnterExecCommand = false;
        } else {
          result = this._callCmdFn('execCommand', arguments);
          !me.__hasEnterExecCommand &&
            !cmd.ignoreContentChange &&
            !me._ignoreContentChange &&
            me.fireEvent('contentchange');
        }
        !me.__hasEnterExecCommand && !cmd.ignoreContentChange && !me._ignoreContentChange && me._selectionChange();
        return result;
      },
      queryCommandState: function (cmdName) {
        return this._callCmdFn('queryCommandState', arguments);
      },
      queryCommandValue: function (cmdName) {
        return this._callCmdFn('queryCommandValue', arguments);
      },
      hasContents: function (tags) {
        if (tags) {
          for (var i = 0, ci; (ci = tags[i++]); ) {
            if (this.document.getElementsByTagName(ci).length > 0) {
              return true;
            }
          }
        }
        if (!domUtils.isEmptyBlock(this.body)) {
          return true;
        }
        tags = ['div'];
        for (i = 0; (ci = tags[i++]); ) {
          var nodes = domUtils.getElementsByTagName(this.document, ci);
          for (var n = 0, cn; (cn = nodes[n++]); ) {
            if (domUtils.isCustomeNode(cn)) {
              return true;
            }
          }
        }
        tags = ['video', 'iframe'];
        for (i = 0; (ci = tags[i++]); ) {
          var nodes = domUtils.getElementsByTagName(this.document, ci);
          for (var n = 0, cn; (cn = nodes[n++]); ) {
            return true;
          }
        }
        return false;
      },
      reset: function () {
        this.clear();
        this.fireEvent('reset');
      },
      clear: function () {
        this.setContent('');
      },
      setEnabled: function () {
        var me = this,
          range;
        if (me.body.contentEditable === 'false') {
          me.body.contentEditable = true;
          range = me.selection.getRange();
          try {
            range.moveToBookmark(me.lastBk);
            delete me.lastBk;
          } catch (e) {
            range.setStartAtFirst(me.body).collapse(true);
          }
          range.select(true);
          if (me.bkqueryCommandState) {
            me.queryCommandState = me.bkqueryCommandState;
            delete me.bkqueryCommandState;
          }
          if (me.bkqueryCommandValue) {
            me.queryCommandValue = me.bkqueryCommandValue;
            delete me.bkqueryCommandValue;
          }
          me.fireEvent('selectionchange');
        }
      },
      enable: function () {
        return this.setEnabled();
      },
      setDisabled: function (except) {
        var me = this;
        except = except ? (utils.isArray(except) ? except : [except]) : [];
        if (me.body.contentEditable == 'true') {
          if (!me.lastBk) {
            me.lastBk = me.selection.getRange().createBookmark(true);
          }
          me.body.contentEditable = false;
          me.bkqueryCommandState = me.queryCommandState;
          me.bkqueryCommandValue = me.queryCommandValue;
          me.queryCommandState = function (type) {
            if (utils.indexOf(except, type) != -1) {
              return me.bkqueryCommandState.apply(me, arguments);
            }
            return -1;
          };
          me.queryCommandValue = function (type) {
            if (utils.indexOf(except, type) != -1) {
              return me.bkqueryCommandValue.apply(me, arguments);
            }
            return null;
          };
          me.fireEvent('selectionchange');
        }
      },
      disable: function (except) {
        return this.setDisabled(except);
      },
      _setDefaultContent: (function () {
        function clear() {
          var me = this;
          if (me.document.getElementById('initContent')) {
            me.body.innerHTML = '<p>' + (ie ? '' : '<br/>') + '</p>';
            me.removeListener('firstBeforeExecCommand focus', clear);
            setTimeout(function () {
              me.focus();
              me._selectionChange();
            }, 0);
          }
        }
        return function (cont) {
          var me = this;
          me.body.innerHTML = '<p id="initContent">' + cont + '</p>';
          me.addListener('firstBeforeExecCommand focus', clear);
        };
      })(),
      setShow: function () {
        var me = this,
          range = me.selection.getRange();
        if (me.container.style.display == 'none') {
          try {
            range.moveToBookmark(me.lastBk);
            delete me.lastBk;
          } catch (e) {
            range.setStartAtFirst(me.body).collapse(true);
          }
          setTimeout(function () {
            range.select(true);
          }, 100);
          me.container.style.display = '';
        }
      },
      show: function () {
        return this.setShow();
      },
      setHide: function () {
        var me = this;
        if (!me.lastBk) {
          me.lastBk = me.selection.getRange().createBookmark(true);
        }
        me.container.style.display = 'none';
      },
      hide: function () {
        return this.setHide();
      },
      getLang: function (path) {
        var lang = UE.I18N[this.options.lang];
        if (!lang) {
          throw Error('not import language file');
        }
        path = (path || '').split('.');
        for (var i = 0, ci; (ci = path[i++]); ) {
          lang = lang[ci];
          if (!lang) break;
        }
        return lang;
      },
      getContentLength: function (ingoneHtml, tagNames) {
        var count = this.getContent(false, false, true).length;
        if (ingoneHtml) {
          tagNames = (tagNames || []).concat(['hr', 'img', 'iframe']);
          count = this.getContentTxt().replace(/[\t\r\n]+/g, '').length;
          for (var i = 0, ci; (ci = tagNames[i++]); ) {
            count += this.document.getElementsByTagName(ci).length;
          }
        }
        return count;
      },
      getScrollTop: function () {
        return Math.max(this.document.documentElement.scrollTop, this.document.body.scrollTop);
      },
      getScrollLeft: function () {
        return Math.max(this.document.documentElement.scrollLeft, this.document.body.scrollLeft);
      },
      addInputRule: function (rule) {
        this.inputRules.push(rule);
      },
      filterInputRule: function (root) {
        for (var i = 0, ci; (ci = this.inputRules[i++]); ) {
          ci.call(this, root);
        }
      },
      addOutputRule: function (rule) {
        this.outputRules.push(rule);
      },
      filterOutputRule: function (root) {
        for (var i = 0, ci; (ci = this.outputRules[i++]); ) {
          ci.call(this, root);
        }
      },
      getActionUrl: function (action) {
        var serverUrl = this.getOpt('serverUrl');
        if (!action) {
          return serverUrl;
        }
        var actionName = this.getOpt(action) || action,
          imageUrl = this.getOpt('imageUrl');
        if (!serverUrl && imageUrl) {
          serverUrl = imageUrl.replace(/^(.*[\/]).+([\.].+)$/, '$1controller$2');
        }
        if (serverUrl) {
          serverUrl = serverUrl + (serverUrl.indexOf('?') === -1 ? '?' : '&') + 'action=' + (actionName || '');
          return utils.formatUrl(serverUrl);
        } else {
          return '';
        }
      },
      tipError: function (msg, option) {
        this.tip(msg, Object.assign({ type: 'error' }, option));
      },
      tipSuccess: function (msg, option) {
        this.tip(msg, Object.assign({ type: 'success' }, option));
      },
      tip: function (msg, option) {
        var exists = document.getElementById('EditorTipBox');
        if (exists) {
          document.body.removeChild(exists);
        }
        option = Object.assign({ type: 'success', duration: 3e3 }, option);
        var html = [
          '<div class="editor-tip editor-tip-' +
            option.type +
            '" style="opacity:0;position: fixed; top: 10px; left: 50%; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); background: #FFF; z-index: 9999; border-radius: 5px; font-size: 13px; line-height: 30px; padding: 0 10px;">',
          option.type === 'error'
            ? '<i class="edui-iconfont" style="color:#d31919;margin-right:5px;font-size:16px;vertical-align:top;">&#xe6a7;</i>'
            : '',
          option.type === 'success'
            ? '<i class="edui-iconfont" style="color:#19ba21;margin-right:5px;font-size:16px;vertical-align:top;">&#xe7fc;</i>'
            : '',
          msg,
          '</div>',
        ].join('');
        var tip = document.createElement('div');
        tip.innerHTML = html;
        tip.id = 'EditorTipBox';
        document.body.appendChild(tip);
        var tipBox = tip.querySelector('.editor-tip');
        var tipBoxWidth = tipBox.offsetWidth;
        tipBox.style.marginLeft = -tipBoxWidth / 2 + 'px';
        tipBox.style.opacity = 1;
        setTimeout(function () {
          document.body.removeChild(tip);
        }, option.duration);
      },
    };
    utils.inherits(Editor, EventBase);
  })();
  UE.Editor.defaultOptions = function (editor) {
    var _url = editor.options.UEDITOR_HOME_URL;
    return {
      isShow: true,
      initialContent: '',
      initialStyle: '',
      autoClearinitialContent: false,
      iframeCssUrl: _url + 'themes/iframe.css?c20ec247',
      iframeCssUrlsAddition: [],
      textarea: '',
      focus: false,
      focusInEnd: true,
      autoClearEmptyNode: true,
      fullscreen: false,
      readonly: false,
      zIndex: 999,
      imagePopup: true,
      enterTag: 'p',
      customDomain: false,
      lang: 'zh-cn',
      langPath: _url + 'lang/',
      theme: 'default',
      themePath: _url + 'themes/',
      allHtmlEnabled: false,
      scaleEnabled: false,
      tableNativeEditInFF: false,
      autoSyncData: true,
      fileNameFormat: '{time}{rand:6}',
    };
  };
  (function () {
    UE.Editor.prototype.loadServerConfig = function () {
      var me = this;
      setTimeout(function () {
        if (me.options.loadConfigFromServer === false) {
          return;
        }
        try {
          me.options.imageUrl &&
            me.setOpt('serverUrl', me.options.imageUrl.replace(/^(.*[\/]).+([\.].+)$/, '$1controller$2'));
          var configUrl = me.getActionUrl('config'),
            isJsonp = utils.isCrossDomainUrl(configUrl);
          me._serverConfigLoaded = false;
          configUrl &&
            UE.ajax.request(configUrl, {
              method: 'GET',
              dataType: isJsonp ? 'jsonp' : '',
              headers: me.options.serverHeaders || {},
              onsuccess: function (r) {
                try {
                  var config = isJsonp ? r : eval('(' + r.responseText + ')');
                  config = me.options.serverResponsePrepare(config);
                  me.options = utils.merge(me.options, config);
                  me.fireEvent('serverConfigLoaded');
                  me._serverConfigLoaded = true;
                } catch (e) {
                  showErrorMsg(me.getLang('loadconfigFormatError') + ':' + e);
                }
              },
              onerror: function () {
                showErrorMsg(me.getLang('loadconfigHttpError'));
              },
            });
        } catch (e) {
          showErrorMsg(me.getLang('loadconfigError'));
        }
      });
      function showErrorMsg(msg) {
        console && console.error(msg);
      }
    };
    UE.Editor.prototype.isServerConfigLoaded = function () {
      var me = this;
      return me._serverConfigLoaded || false;
    };
    UE.Editor.prototype.afterConfigReady = function (handler) {
      if (!handler || !utils.isFunction(handler)) return;
      var me = this;
      var readyHandler = function () {
        handler.apply(me, arguments);
        me.removeListener('serverConfigLoaded', readyHandler);
      };
      if (me.isServerConfigLoaded()) {
        handler.call(me, 'serverConfigLoaded');
      } else {
        me.addListener('serverConfigLoaded', readyHandler);
      }
    };
  })();
  UE.ajax = (function () {
    var fnStr = 'XMLHttpRequest()';
    try {
      new ActiveXObject('Msxml2.XMLHTTP');
      fnStr = "ActiveXObject('Msxml2.XMLHTTP')";
    } catch (e) {
      try {
        new ActiveXObject('Microsoft.XMLHTTP');
        fnStr = "ActiveXObject('Microsoft.XMLHTTP')";
      } catch (e) {}
    }
    var creatAjaxRequest = new Function('return new ' + fnStr);
    function json2str(json) {
      var strArr = [];
      for (var i in json) {
        if (i == 'method' || i == 'timeout' || i == 'async' || i == 'dataType' || i == 'callback') continue;
        if (json[i] == undefined || json[i] == null) continue;
        if (!((typeof json[i]).toLowerCase() == 'function' || (typeof json[i]).toLowerCase() == 'object')) {
          strArr.push(encodeURIComponent(i) + '=' + encodeURIComponent(json[i]));
        } else if (utils.isArray(json[i])) {
          for (var j = 0; j < json[i].length; j++) {
            strArr.push(encodeURIComponent(i) + '[]=' + encodeURIComponent(json[i][j]));
          }
        }
      }
      return strArr.join('&');
    }
    function doAjax(url, ajaxOptions) {
      var xhr = creatAjaxRequest(),
        timeIsOut = false,
        defaultAjaxOptions = {
          method: 'POST',
          timeout: 5e3,
          async: true,
          headers: {},
          data: {},
          onsuccess: function () {},
          onerror: function () {},
        };
      if (typeof url === 'object') {
        ajaxOptions = url;
        url = ajaxOptions.url;
      }
      if (!xhr || !url) return;
      var ajaxOpts = ajaxOptions ? utils.extend(defaultAjaxOptions, ajaxOptions) : defaultAjaxOptions;
      var submitStr = json2str(ajaxOpts);
      if (!utils.isEmptyObject(ajaxOpts.data)) {
        submitStr += (submitStr ? '&' : '') + json2str(ajaxOpts.data);
      }
      var timerID = setTimeout(function () {
        if (xhr.readyState !== 4) {
          timeIsOut = true;
          xhr.abort();
          clearTimeout(timerID);
        }
      }, ajaxOpts.timeout);
      var method = ajaxOpts.method.toUpperCase();
      var str =
        url + (url.indexOf('?') === -1 ? '?' : '&') + (method === 'POST' ? '' : submitStr + '&noCache=' + +new Date());
      xhr.open(method, str, ajaxOpts.async);
      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
          if (!timeIsOut && xhr.status === 200) {
            ajaxOpts.onsuccess(xhr);
          } else {
            ajaxOpts.onerror(xhr);
          }
        }
      };
      if (ajaxOpts.headers) {
        for (var key in ajaxOpts.headers) {
          xhr.setRequestHeader(key, ajaxOpts.headers[key]);
        }
      }
      if (method === 'POST') {
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        xhr.send(submitStr);
      } else {
        xhr.send(null);
      }
    }
    function doJsonp(url, opts) {
      var successhandler = opts.onsuccess || function () {},
        scr = document.createElement('SCRIPT'),
        options = opts || {},
        charset = options['charset'],
        callbackField = options['jsonp'] || 'callback',
        callbackFnName,
        timeOut = options['timeOut'] || 0,
        timer,
        reg = new RegExp('(\\?|&)' + callbackField + '=([^&]*)'),
        matches;
      if (utils.isFunction(successhandler)) {
        callbackFnName = 'bd__editor__' + Math.floor(Math.random() * 2147483648).toString(36);
        window[callbackFnName] = getCallBack(0);
      } else if (utils.isString(successhandler)) {
        callbackFnName = successhandler;
      } else {
        if ((matches = reg.exec(url))) {
          callbackFnName = matches[2];
        }
      }
      url = url.replace(reg, '$1' + callbackField + '=' + callbackFnName);
      if (url.search(reg) < 0) {
        url += (url.indexOf('?') < 0 ? '?' : '&') + callbackField + '=' + callbackFnName;
      }
      var queryStr = json2str(opts);
      if (!utils.isEmptyObject(opts.data)) {
        queryStr += (queryStr ? '&' : '') + json2str(opts.data);
      }
      if (queryStr) {
        url = url.replace(/\?/, '?' + queryStr + '&');
      }
      scr.onerror = getCallBack(1);
      if (timeOut) {
        timer = setTimeout(getCallBack(1), timeOut);
      }
      createScriptTag(scr, url, charset);
      function createScriptTag(scr, url, charset) {
        scr.setAttribute('type', 'text/javascript');
        scr.setAttribute('defer', 'defer');
        charset && scr.setAttribute('charset', charset);
        scr.setAttribute('src', url);
        document.getElementsByTagName('head')[0].appendChild(scr);
      }
      function getCallBack(onTimeOut) {
        return function () {
          try {
            if (onTimeOut) {
              options.onerror && options.onerror();
            } else {
              try {
                clearTimeout(timer);
                successhandler.apply(window, arguments);
              } catch (e) {}
            }
          } catch (exception) {
            options.onerror && options.onerror.call(window, exception);
          } finally {
            options.oncomplete && options.oncomplete.apply(window, arguments);
            scr.parentNode && scr.parentNode.removeChild(scr);
            window[callbackFnName] = null;
            try {
              delete window[callbackFnName];
            } catch (e) {}
          }
        };
      }
    }
    return {
      request: function (url, opts) {
        if (opts && opts.dataType === 'jsonp') {
          doJsonp(url, opts);
        } else {
          doAjax(url, opts);
        }
      },
      getJSONP: function (url, data, fn) {
        var opts = { data: data, oncomplete: fn };
        doJsonp(url, opts);
      },
    };
  })();
  UE.api = (function () {
    var axios = null;
    !(function (e, t) {
      axios = t();
    })(this, function () {
      'use strict';
      function e(t) {
        return (
          (e =
            'function' == typeof Symbol && 'symbol' == typeof Symbol.iterator
              ? function (e) {
                  return typeof e;
                }
              : function (e) {
                  return e && 'function' == typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype
                    ? 'symbol'
                    : typeof e;
                }),
          e(t)
        );
      }
      function t(e, t) {
        if (!(e instanceof t)) throw new TypeError('Cannot call a class as a function');
      }
      function n(e, t) {
        for (var n = 0; n < t.length; n++) {
          var r = t[n];
          ((r.enumerable = r.enumerable || !1),
            (r.configurable = !0),
            'value' in r && (r.writable = !0),
            Object.defineProperty(e, r.key, r));
        }
      }
      function r(e, t, r) {
        return (t && n(e.prototype, t), r && n(e, r), Object.defineProperty(e, 'prototype', { writable: !1 }), e);
      }
      function o(e, t) {
        return (
          (function (e) {
            if (Array.isArray(e)) return e;
          })(e) ||
          (function (e, t) {
            var n = null == e ? null : ('undefined' != typeof Symbol && e[Symbol.iterator]) || e['@@iterator'];
            if (null == n) return;
            var r,
              o,
              i = [],
              a = !0,
              s = !1;
            try {
              for (n = n.call(e); !(a = (r = n.next()).done) && (i.push(r.value), !t || i.length !== t); a = !0);
            } catch (e) {
              ((s = !0), (o = e));
            } finally {
              try {
                a || null == n.return || n.return();
              } finally {
                if (s) throw o;
              }
            }
            return i;
          })(e, t) ||
          (function (e, t) {
            if (!e) return;
            if ('string' == typeof e) return i(e, t);
            var n = Object.prototype.toString.call(e).slice(8, -1);
            'Object' === n && e.constructor && (n = e.constructor.name);
            if ('Map' === n || 'Set' === n) return Array.from(e);
            if ('Arguments' === n || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return i(e, t);
          })(e, t) ||
          (function () {
            throw new TypeError(
              'Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.',
            );
          })()
        );
      }
      function i(e, t) {
        (null == t || t > e.length) && (t = e.length);
        for (var n = 0, r = new Array(t); n < t; n++) r[n] = e[n];
        return r;
      }
      function a(e, t) {
        return function () {
          return e.apply(t, arguments);
        };
      }
      var s,
        u = Object.prototype.toString,
        c = Object.getPrototypeOf,
        f =
          ((s = Object.create(null)),
          function (e) {
            var t = u.call(e);
            return s[t] || (s[t] = t.slice(8, -1).toLowerCase());
          }),
        l = function (e) {
          return (
            (e = e.toLowerCase()),
            function (t) {
              return f(t) === e;
            }
          );
        },
        d = function (t) {
          return function (n) {
            return e(n) === t;
          };
        },
        p = Array.isArray,
        h = d('undefined');
      var m = l('ArrayBuffer');
      var y = d('string'),
        v = d('function'),
        b = d('number'),
        g = function (t) {
          return null !== t && 'object' === e(t);
        },
        w = function (e) {
          if ('object' !== f(e)) return !1;
          var t = c(e);
          return !(
            (null !== t && t !== Object.prototype && null !== Object.getPrototypeOf(t)) ||
            Symbol.toStringTag in e ||
            Symbol.iterator in e
          );
        },
        E = l('Date'),
        O = l('File'),
        S = l('Blob'),
        R = l('FileList'),
        A = l('URLSearchParams');
      function T(t, n) {
        var r,
          o,
          i = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : {},
          a = i.allOwnKeys,
          s = void 0 !== a && a;
        if (null != t)
          if (('object' !== e(t) && (t = [t]), p(t))) for (r = 0, o = t.length; r < o; r++) n.call(null, t[r], r, t);
          else {
            var u,
              c = s ? Object.getOwnPropertyNames(t) : Object.keys(t),
              f = c.length;
            for (r = 0; r < f; r++) ((u = c[r]), n.call(null, t[u], u, t));
          }
      }
      function j(e, t) {
        t = t.toLowerCase();
        for (var n, r = Object.keys(e), o = r.length; o-- > 0; ) if (t === (n = r[o]).toLowerCase()) return n;
        return null;
      }
      var N =
          'undefined' != typeof globalThis
            ? globalThis
            : 'undefined' != typeof self
              ? self
              : 'undefined' != typeof window
                ? window
                : global,
        C = function (e) {
          return !h(e) && e !== N;
        };
      var x,
        P =
          ((x = 'undefined' != typeof Uint8Array && c(Uint8Array)),
          function (e) {
            return x && e instanceof x;
          }),
        k = l('HTMLFormElement'),
        U = (function (e) {
          var t = Object.prototype.hasOwnProperty;
          return function (e, n) {
            return t.call(e, n);
          };
        })(),
        _ = l('RegExp'),
        F = function (e, t) {
          var n = Object.getOwnPropertyDescriptors(e),
            r = {};
          (T(n, function (n, o) {
            !1 !== t(n, o, e) && (r[o] = n);
          }),
            Object.defineProperties(e, r));
        },
        B = 'abcdefghijklmnopqrstuvwxyz',
        L = '0123456789',
        D = { DIGIT: L, ALPHA: B, ALPHA_DIGIT: B + B.toUpperCase() + L };
      var I = l('AsyncFunction'),
        q = {
          isArray: p,
          isArrayBuffer: m,
          isBuffer: function (e) {
            return (
              null !== e &&
              !h(e) &&
              null !== e.constructor &&
              !h(e.constructor) &&
              v(e.constructor.isBuffer) &&
              e.constructor.isBuffer(e)
            );
          },
          isFormData: function (e) {
            var t;
            return (
              e &&
              (('function' == typeof FormData && e instanceof FormData) ||
                (v(e.append) &&
                  ('formdata' === (t = f(e)) ||
                    ('object' === t && v(e.toString) && '[object FormData]' === e.toString()))))
            );
          },
          isArrayBufferView: function (e) {
            return 'undefined' != typeof ArrayBuffer && ArrayBuffer.isView
              ? ArrayBuffer.isView(e)
              : e && e.buffer && m(e.buffer);
          },
          isString: y,
          isNumber: b,
          isBoolean: function (e) {
            return !0 === e || !1 === e;
          },
          isObject: g,
          isPlainObject: w,
          isUndefined: h,
          isDate: E,
          isFile: O,
          isBlob: S,
          isRegExp: _,
          isFunction: v,
          isStream: function (e) {
            return g(e) && v(e.pipe);
          },
          isURLSearchParams: A,
          isTypedArray: P,
          isFileList: R,
          forEach: T,
          merge: function e() {
            for (
              var t = (C(this) && this) || {},
                n = t.caseless,
                r = {},
                o = function (t, o) {
                  var i = (n && j(r, o)) || o;
                  w(r[i]) && w(t)
                    ? (r[i] = e(r[i], t))
                    : w(t)
                      ? (r[i] = e({}, t))
                      : p(t)
                        ? (r[i] = t.slice())
                        : (r[i] = t);
                },
                i = 0,
                a = arguments.length;
              i < a;
              i++
            )
              arguments[i] && T(arguments[i], o);
            return r;
          },
          extend: function (e, t, n) {
            var r = arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : {},
              o = r.allOwnKeys;
            return (
              T(
                t,
                function (t, r) {
                  n && v(t) ? (e[r] = a(t, n)) : (e[r] = t);
                },
                { allOwnKeys: o },
              ),
              e
            );
          },
          trim: function (e) {
            return e.trim ? e.trim() : e.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
          },
          stripBOM: function (e) {
            return (65279 === e.charCodeAt(0) && (e = e.slice(1)), e);
          },
          inherits: function (e, t, n, r) {
            ((e.prototype = Object.create(t.prototype, r)),
              (e.prototype.constructor = e),
              Object.defineProperty(e, 'super', { value: t.prototype }),
              n && Object.assign(e.prototype, n));
          },
          toFlatObject: function (e, t, n, r) {
            var o,
              i,
              a,
              s = {};
            if (((t = t || {}), null == e)) return t;
            do {
              for (i = (o = Object.getOwnPropertyNames(e)).length; i-- > 0; )
                ((a = o[i]), (r && !r(a, e, t)) || s[a] || ((t[a] = e[a]), (s[a] = !0)));
              e = !1 !== n && c(e);
            } while (e && (!n || n(e, t)) && e !== Object.prototype);
            return t;
          },
          kindOf: f,
          kindOfTest: l,
          endsWith: function (e, t, n) {
            ((e = String(e)), (void 0 === n || n > e.length) && (n = e.length), (n -= t.length));
            var r = e.indexOf(t, n);
            return -1 !== r && r === n;
          },
          toArray: function (e) {
            if (!e) return null;
            if (p(e)) return e;
            var t = e.length;
            if (!b(t)) return null;
            for (var n = new Array(t); t-- > 0; ) n[t] = e[t];
            return n;
          },
          forEachEntry: function (e, t) {
            for (var n, r = (e && e[Symbol.iterator]).call(e); (n = r.next()) && !n.done; ) {
              var o = n.value;
              t.call(e, o[0], o[1]);
            }
          },
          matchAll: function (e, t) {
            for (var n, r = []; null !== (n = e.exec(t)); ) r.push(n);
            return r;
          },
          isHTMLForm: k,
          hasOwnProperty: U,
          hasOwnProp: U,
          reduceDescriptors: F,
          freezeMethods: function (e) {
            F(e, function (t, n) {
              if (v(e) && -1 !== ['arguments', 'caller', 'callee'].indexOf(n)) return !1;
              var r = e[n];
              v(r) &&
                ((t.enumerable = !1),
                'writable' in t
                  ? (t.writable = !1)
                  : t.set ||
                    (t.set = function () {
                      throw Error("Can not rewrite read-only method '" + n + "'");
                    }));
            });
          },
          toObjectSet: function (e, t) {
            var n = {},
              r = function (e) {
                e.forEach(function (e) {
                  n[e] = !0;
                });
              };
            return (p(e) ? r(e) : r(String(e).split(t)), n);
          },
          toCamelCase: function (e) {
            return e.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g, function (e, t, n) {
              return t.toUpperCase() + n;
            });
          },
          noop: function () {},
          toFiniteNumber: function (e, t) {
            return ((e = +e), Number.isFinite(e) ? e : t);
          },
          findKey: j,
          global: N,
          isContextDefined: C,
          ALPHABET: D,
          generateString: function () {
            for (
              var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : 16,
                t = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : D.ALPHA_DIGIT,
                n = '',
                r = t.length;
              e--;

            )
              n += t[(Math.random() * r) | 0];
            return n;
          },
          isSpecCompliantForm: function (e) {
            return !!(e && v(e.append) && 'FormData' === e[Symbol.toStringTag] && e[Symbol.iterator]);
          },
          toJSONObject: function (e) {
            var t = new Array(10);
            return (function e(n, r) {
              if (g(n)) {
                if (t.indexOf(n) >= 0) return;
                if (!('toJSON' in n)) {
                  t[r] = n;
                  var o = p(n) ? [] : {};
                  return (
                    T(n, function (t, n) {
                      var i = e(t, r + 1);
                      !h(i) && (o[n] = i);
                    }),
                    (t[r] = void 0),
                    o
                  );
                }
              }
              return n;
            })(e, 0);
          },
          isAsyncFn: I,
          isThenable: function (e) {
            return e && (g(e) || v(e)) && v(e.then) && v(e.catch);
          },
        };
      function M(e, t, n, r, o) {
        (Error.call(this),
          Error.captureStackTrace ? Error.captureStackTrace(this, this.constructor) : (this.stack = new Error().stack),
          (this.message = e),
          (this.name = 'AxiosError'),
          t && (this.code = t),
          n && (this.config = n),
          r && (this.request = r),
          o && (this.response = o));
      }
      q.inherits(M, Error, {
        toJSON: function () {
          return {
            message: this.message,
            name: this.name,
            description: this.description,
            number: this.number,
            fileName: this.fileName,
            lineNumber: this.lineNumber,
            columnNumber: this.columnNumber,
            stack: this.stack,
            config: q.toJSONObject(this.config),
            code: this.code,
            status: this.response && this.response.status ? this.response.status : null,
          };
        },
      });
      var z = M.prototype,
        H = {};
      ([
        'ERR_BAD_OPTION_VALUE',
        'ERR_BAD_OPTION',
        'ECONNABORTED',
        'ETIMEDOUT',
        'ERR_NETWORK',
        'ERR_FR_TOO_MANY_REDIRECTS',
        'ERR_DEPRECATED',
        'ERR_BAD_RESPONSE',
        'ERR_BAD_REQUEST',
        'ERR_CANCELED',
        'ERR_NOT_SUPPORT',
        'ERR_INVALID_URL',
      ].forEach(function (e) {
        H[e] = { value: e };
      }),
        Object.defineProperties(M, H),
        Object.defineProperty(z, 'isAxiosError', { value: !0 }),
        (M.from = function (e, t, n, r, o, i) {
          var a = Object.create(z);
          return (
            q.toFlatObject(
              e,
              a,
              function (e) {
                return e !== Error.prototype;
              },
              function (e) {
                return 'isAxiosError' !== e;
              },
            ),
            M.call(a, e.message, t, n, r, o),
            (a.cause = e),
            (a.name = e.name),
            i && Object.assign(a, i),
            a
          );
        }));
      function J(e) {
        return q.isPlainObject(e) || q.isArray(e);
      }
      function W(e) {
        return q.endsWith(e, '[]') ? e.slice(0, -2) : e;
      }
      function K(e, t, n) {
        return e
          ? e
              .concat(t)
              .map(function (e, t) {
                return ((e = W(e)), !n && t ? '[' + e + ']' : e);
              })
              .join(n ? '.' : '')
          : t;
      }
      var V = q.toFlatObject(q, {}, null, function (e) {
        return /^is[A-Z]/.test(e);
      });
      function G(t, n, r) {
        if (!q.isObject(t)) throw new TypeError('target must be an object');
        n = n || new FormData();
        var o = (r = q.toFlatObject(r, { metaTokens: !0, dots: !1, indexes: !1 }, !1, function (e, t) {
            return !q.isUndefined(t[e]);
          })).metaTokens,
          i = r.visitor || f,
          a = r.dots,
          s = r.indexes,
          u = (r.Blob || ('undefined' != typeof Blob && Blob)) && q.isSpecCompliantForm(n);
        if (!q.isFunction(i)) throw new TypeError('visitor must be a function');
        function c(e) {
          if (null === e) return '';
          if (q.isDate(e)) return e.toISOString();
          if (!u && q.isBlob(e)) throw new M('Blob is not supported. Use a Buffer instead.');
          return q.isArrayBuffer(e) || q.isTypedArray(e)
            ? u && 'function' == typeof Blob
              ? new Blob([e])
              : Buffer.from(e)
            : e;
        }
        function f(t, r, i) {
          var u = t;
          if (t && !i && 'object' === e(t))
            if (q.endsWith(r, '{}')) ((r = o ? r : r.slice(0, -2)), (t = JSON.stringify(t)));
            else if (
              (q.isArray(t) &&
                (function (e) {
                  return q.isArray(e) && !e.some(J);
                })(t)) ||
              ((q.isFileList(t) || q.endsWith(r, '[]')) && (u = q.toArray(t)))
            )
              return (
                (r = W(r)),
                u.forEach(function (e, t) {
                  !q.isUndefined(e) &&
                    null !== e &&
                    n.append(!0 === s ? K([r], t, a) : null === s ? r : r + '[]', c(e));
                }),
                !1
              );
          return !!J(t) || (n.append(K(i, r, a), c(t)), !1);
        }
        var l = [],
          d = Object.assign(V, { defaultVisitor: f, convertValue: c, isVisitable: J });
        if (!q.isObject(t)) throw new TypeError('data must be an object');
        return (
          (function e(t, r) {
            if (!q.isUndefined(t)) {
              if (-1 !== l.indexOf(t)) throw Error('Circular reference detected in ' + r.join('.'));
              (l.push(t),
                q.forEach(t, function (t, o) {
                  !0 === (!(q.isUndefined(t) || null === t) && i.call(n, t, q.isString(o) ? o.trim() : o, r, d)) &&
                    e(t, r ? r.concat(o) : [o]);
                }),
                l.pop());
            }
          })(t),
          n
        );
      }
      function $(e) {
        var t = { '!': '%21', "'": '%27', '(': '%28', ')': '%29', '~': '%7E', '%20': '+', '%00': '\0' };
        return encodeURIComponent(e).replace(/[!'()~]|%20|%00/g, function (e) {
          return t[e];
        });
      }
      function X(e, t) {
        ((this._pairs = []), e && G(e, this, t));
      }
      var Q = X.prototype;
      function Z(e) {
        return encodeURIComponent(e)
          .replace(/%3A/gi, ':')
          .replace(/%24/g, '$')
          .replace(/%2C/gi, ',')
          .replace(/%20/g, '+')
          .replace(/%5B/gi, '[')
          .replace(/%5D/gi, ']');
      }
      function Y(e, t, n) {
        if (!t) return e;
        var r,
          o = (n && n.encode) || Z,
          i = n && n.serialize;
        if ((r = i ? i(t, n) : q.isURLSearchParams(t) ? t.toString() : new X(t, n).toString(o))) {
          var a = e.indexOf('#');
          (-1 !== a && (e = e.slice(0, a)), (e += (-1 === e.indexOf('?') ? '?' : '&') + r));
        }
        return e;
      }
      ((Q.append = function (e, t) {
        this._pairs.push([e, t]);
      }),
        (Q.toString = function (e) {
          var t = e
            ? function (t) {
                return e.call(this, t, $);
              }
            : $;
          return this._pairs
            .map(function (e) {
              return t(e[0]) + '=' + t(e[1]);
            }, '')
            .join('&');
        }));
      var ee,
        te = (function () {
          function e() {
            (t(this, e), (this.handlers = []));
          }
          return (
            r(e, [
              {
                key: 'use',
                value: function (e, t, n) {
                  return (
                    this.handlers.push({
                      fulfilled: e,
                      rejected: t,
                      synchronous: !!n && n.synchronous,
                      runWhen: n ? n.runWhen : null,
                    }),
                    this.handlers.length - 1
                  );
                },
              },
              {
                key: 'eject',
                value: function (e) {
                  this.handlers[e] && (this.handlers[e] = null);
                },
              },
              {
                key: 'clear',
                value: function () {
                  this.handlers && (this.handlers = []);
                },
              },
              {
                key: 'forEach',
                value: function (e) {
                  q.forEach(this.handlers, function (t) {
                    null !== t && e(t);
                  });
                },
              },
            ]),
            e
          );
        })(),
        ne = { silentJSONParsing: !0, forcedJSONParsing: !0, clarifyTimeoutError: !1 },
        re = {
          isBrowser: !0,
          classes: {
            URLSearchParams: 'undefined' != typeof URLSearchParams ? URLSearchParams : X,
            FormData: 'undefined' != typeof FormData ? FormData : null,
            Blob: 'undefined' != typeof Blob ? Blob : null,
          },
          isStandardBrowserEnv:
            ('undefined' == typeof navigator ||
              ('ReactNative' !== (ee = navigator.product) && 'NativeScript' !== ee && 'NS' !== ee)) &&
            'undefined' != typeof window &&
            'undefined' != typeof document,
          isStandardBrowserWebWorkerEnv:
            'undefined' != typeof WorkerGlobalScope &&
            self instanceof WorkerGlobalScope &&
            'function' == typeof self.importScripts,
          protocols: ['http', 'https', 'file', 'blob', 'url', 'data'],
        };
      function oe(e) {
        function t(e, n, r, o) {
          var i = e[o++],
            a = Number.isFinite(+i),
            s = o >= e.length;
          return (
            (i = !i && q.isArray(r) ? r.length : i),
            s
              ? (q.hasOwnProp(r, i) ? (r[i] = [r[i], n]) : (r[i] = n), !a)
              : ((r[i] && q.isObject(r[i])) || (r[i] = []),
                t(e, n, r[i], o) &&
                  q.isArray(r[i]) &&
                  (r[i] = (function (e) {
                    var t,
                      n,
                      r = {},
                      o = Object.keys(e),
                      i = o.length;
                    for (t = 0; t < i; t++) r[(n = o[t])] = e[n];
                    return r;
                  })(r[i])),
                !a)
          );
        }
        if (q.isFormData(e) && q.isFunction(e.entries)) {
          var n = {};
          return (
            q.forEachEntry(e, function (e, r) {
              t(
                (function (e) {
                  return q.matchAll(/\w+|\[(\w*)]/g, e).map(function (e) {
                    return '[]' === e[0] ? '' : e[1] || e[0];
                  });
                })(e),
                r,
                n,
                0,
              );
            }),
            n
          );
        }
        return null;
      }
      var ie = { 'Content-Type': void 0 };
      var ae = {
        transitional: ne,
        adapter: ['xhr', 'http'],
        transformRequest: [
          function (e, t) {
            var n,
              r = t.getContentType() || '',
              o = r.indexOf('application/json') > -1,
              i = q.isObject(e);
            if ((i && q.isHTMLForm(e) && (e = new FormData(e)), q.isFormData(e)))
              return o && o ? JSON.stringify(oe(e)) : e;
            if (q.isArrayBuffer(e) || q.isBuffer(e) || q.isStream(e) || q.isFile(e) || q.isBlob(e)) return e;
            if (q.isArrayBufferView(e)) return e.buffer;
            if (q.isURLSearchParams(e))
              return (t.setContentType('application/x-www-form-urlencoded;charset=utf-8', !1), e.toString());
            if (i) {
              if (r.indexOf('application/x-www-form-urlencoded') > -1)
                return (function (e, t) {
                  return G(
                    e,
                    new re.classes.URLSearchParams(),
                    Object.assign(
                      {
                        visitor: function (e, t, n, r) {
                          return re.isNode && q.isBuffer(e)
                            ? (this.append(t, e.toString('base64')), !1)
                            : r.defaultVisitor.apply(this, arguments);
                        },
                      },
                      t,
                    ),
                  );
                })(e, this.formSerializer).toString();
              if ((n = q.isFileList(e)) || r.indexOf('multipart/form-data') > -1) {
                var a = this.env && this.env.FormData;
                return G(n ? { 'files[]': e } : e, a && new a(), this.formSerializer);
              }
            }
            return i || o
              ? (t.setContentType('application/json', !1),
                (function (e, t, n) {
                  if (q.isString(e))
                    try {
                      return ((t || JSON.parse)(e), q.trim(e));
                    } catch (e) {
                      if ('SyntaxError' !== e.name) throw e;
                    }
                  return (n || JSON.stringify)(e);
                })(e))
              : e;
          },
        ],
        transformResponse: [
          function (e) {
            var t = this.transitional || ae.transitional,
              n = t && t.forcedJSONParsing,
              r = 'json' === this.responseType;
            if (e && q.isString(e) && ((n && !this.responseType) || r)) {
              var o = !(t && t.silentJSONParsing) && r;
              try {
                return JSON.parse(e);
              } catch (e) {
                if (o) {
                  if ('SyntaxError' === e.name) throw M.from(e, M.ERR_BAD_RESPONSE, this, null, this.response);
                  throw e;
                }
              }
            }
            return e;
          },
        ],
        timeout: 0,
        xsrfCookieName: 'XSRF-TOKEN',
        xsrfHeaderName: 'X-XSRF-TOKEN',
        maxContentLength: -1,
        maxBodyLength: -1,
        env: { FormData: re.classes.FormData, Blob: re.classes.Blob },
        validateStatus: function (e) {
          return e >= 200 && e < 300;
        },
        headers: { common: { Accept: 'application/json, text/plain, */*' } },
      };
      (q.forEach(['delete', 'get', 'head'], function (e) {
        ae.headers[e] = {};
      }),
        q.forEach(['post', 'put', 'patch'], function (e) {
          ae.headers[e] = q.merge(ie);
        }));
      var se = ae,
        ue = q.toObjectSet([
          'age',
          'authorization',
          'content-length',
          'content-type',
          'etag',
          'expires',
          'from',
          'host',
          'if-modified-since',
          'if-unmodified-since',
          'last-modified',
          'location',
          'max-forwards',
          'proxy-authorization',
          'referer',
          'retry-after',
          'user-agent',
        ]),
        ce = Symbol('internals');
      function fe(e) {
        return e && String(e).trim().toLowerCase();
      }
      function le(e) {
        return !1 === e || null == e ? e : q.isArray(e) ? e.map(le) : String(e);
      }
      function de(e, t, n, r, o) {
        return q.isFunction(r)
          ? r.call(this, t, n)
          : (o && (t = n),
            q.isString(t) ? (q.isString(r) ? -1 !== t.indexOf(r) : q.isRegExp(r) ? r.test(t) : void 0) : void 0);
      }
      var pe = (function (e, n) {
        function i(e) {
          (t(this, i), e && this.set(e));
        }
        return (
          r(
            i,
            [
              {
                key: 'set',
                value: function (e, t, n) {
                  var r = this;
                  function o(e, t, n) {
                    var o = fe(t);
                    if (!o) throw new Error('header name must be a non-empty string');
                    var i = q.findKey(r, o);
                    (!i || void 0 === r[i] || !0 === n || (void 0 === n && !1 !== r[i])) && (r[i || t] = le(e));
                  }
                  var i,
                    a,
                    s,
                    u,
                    c,
                    f = function (e, t) {
                      return q.forEach(e, function (e, n) {
                        return o(e, n, t);
                      });
                    };
                  return (
                    q.isPlainObject(e) || e instanceof this.constructor
                      ? f(e, t)
                      : q.isString(e) && (e = e.trim()) && !/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(e.trim())
                        ? f(
                            ((c = {}),
                            (i = e) &&
                              i.split('\n').forEach(function (e) {
                                ((u = e.indexOf(':')),
                                  (a = e.substring(0, u).trim().toLowerCase()),
                                  (s = e.substring(u + 1).trim()),
                                  !a ||
                                    (c[a] && ue[a]) ||
                                    ('set-cookie' === a
                                      ? c[a]
                                        ? c[a].push(s)
                                        : (c[a] = [s])
                                      : (c[a] = c[a] ? c[a] + ', ' + s : s)));
                              }),
                            c),
                            t,
                          )
                        : null != e && o(t, e, n),
                    this
                  );
                },
              },
              {
                key: 'get',
                value: function (e, t) {
                  if ((e = fe(e))) {
                    var n = q.findKey(this, e);
                    if (n) {
                      var r = this[n];
                      if (!t) return r;
                      if (!0 === t)
                        return (function (e) {
                          for (
                            var t, n = Object.create(null), r = /([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;
                            (t = r.exec(e));

                          )
                            n[t[1]] = t[2];
                          return n;
                        })(r);
                      if (q.isFunction(t)) return t.call(this, r, n);
                      if (q.isRegExp(t)) return t.exec(r);
                      throw new TypeError('parser must be boolean|regexp|function');
                    }
                  }
                },
              },
              {
                key: 'has',
                value: function (e, t) {
                  if ((e = fe(e))) {
                    var n = q.findKey(this, e);
                    return !(!n || void 0 === this[n] || (t && !de(0, this[n], n, t)));
                  }
                  return !1;
                },
              },
              {
                key: 'delete',
                value: function (e, t) {
                  var n = this,
                    r = !1;
                  function o(e) {
                    if ((e = fe(e))) {
                      var o = q.findKey(n, e);
                      !o || (t && !de(0, n[o], o, t)) || (delete n[o], (r = !0));
                    }
                  }
                  return (q.isArray(e) ? e.forEach(o) : o(e), r);
                },
              },
              {
                key: 'clear',
                value: function (e) {
                  for (var t = Object.keys(this), n = t.length, r = !1; n--; ) {
                    var o = t[n];
                    (e && !de(0, this[o], o, e, !0)) || (delete this[o], (r = !0));
                  }
                  return r;
                },
              },
              {
                key: 'normalize',
                value: function (e) {
                  var t = this,
                    n = {};
                  return (
                    q.forEach(this, function (r, o) {
                      var i = q.findKey(n, o);
                      if (i) return ((t[i] = le(r)), void delete t[o]);
                      var a = e
                        ? (function (e) {
                            return e
                              .trim()
                              .toLowerCase()
                              .replace(/([a-z\d])(\w*)/g, function (e, t, n) {
                                return t.toUpperCase() + n;
                              });
                          })(o)
                        : String(o).trim();
                      (a !== o && delete t[o], (t[a] = le(r)), (n[a] = !0));
                    }),
                    this
                  );
                },
              },
              {
                key: 'concat',
                value: function () {
                  for (var e, t = arguments.length, n = new Array(t), r = 0; r < t; r++) n[r] = arguments[r];
                  return (e = this.constructor).concat.apply(e, [this].concat(n));
                },
              },
              {
                key: 'toJSON',
                value: function (e) {
                  var t = Object.create(null);
                  return (
                    q.forEach(this, function (n, r) {
                      null != n && !1 !== n && (t[r] = e && q.isArray(n) ? n.join(', ') : n);
                    }),
                    t
                  );
                },
              },
              {
                key: Symbol.iterator,
                value: function () {
                  return Object.entries(this.toJSON())[Symbol.iterator]();
                },
              },
              {
                key: 'toString',
                value: function () {
                  return Object.entries(this.toJSON())
                    .map(function (e) {
                      var t = o(e, 2);
                      return t[0] + ': ' + t[1];
                    })
                    .join('\n');
                },
              },
              {
                key: Symbol.toStringTag,
                get: function () {
                  return 'AxiosHeaders';
                },
              },
            ],
            [
              {
                key: 'from',
                value: function (e) {
                  return e instanceof this ? e : new this(e);
                },
              },
              {
                key: 'concat',
                value: function (e) {
                  for (var t = new this(e), n = arguments.length, r = new Array(n > 1 ? n - 1 : 0), o = 1; o < n; o++)
                    r[o - 1] = arguments[o];
                  return (
                    r.forEach(function (e) {
                      return t.set(e);
                    }),
                    t
                  );
                },
              },
              {
                key: 'accessor',
                value: function (e) {
                  var t = (this[ce] = this[ce] = { accessors: {} }).accessors,
                    n = this.prototype;
                  function r(e) {
                    var r = fe(e);
                    t[r] ||
                      (!(function (e, t) {
                        var n = q.toCamelCase(' ' + t);
                        ['get', 'set', 'has'].forEach(function (r) {
                          Object.defineProperty(e, r + n, {
                            value: function (e, n, o) {
                              return this[r].call(this, t, e, n, o);
                            },
                            configurable: !0,
                          });
                        });
                      })(n, e),
                      (t[r] = !0));
                  }
                  return (q.isArray(e) ? e.forEach(r) : r(e), this);
                },
              },
            ],
          ),
          i
        );
      })();
      (pe.accessor(['Content-Type', 'Content-Length', 'Accept', 'Accept-Encoding', 'User-Agent', 'Authorization']),
        q.freezeMethods(pe.prototype),
        q.freezeMethods(pe));
      var he = pe;
      function me(e, t) {
        var n = this || se,
          r = t || n,
          o = he.from(r.headers),
          i = r.data;
        return (
          q.forEach(e, function (e) {
            i = e.call(n, i, o.normalize(), t ? t.status : void 0);
          }),
          o.normalize(),
          i
        );
      }
      function ye(e) {
        return !(!e || !e.__CANCEL__);
      }
      function ve(e, t, n) {
        (M.call(this, null == e ? 'canceled' : e, M.ERR_CANCELED, t, n), (this.name = 'CanceledError'));
      }
      q.inherits(ve, M, { __CANCEL__: !0 });
      var be = re.isStandardBrowserEnv
        ? {
            write: function (e, t, n, r, o, i) {
              var a = [];
              (a.push(e + '=' + encodeURIComponent(t)),
                q.isNumber(n) && a.push('expires=' + new Date(n).toGMTString()),
                q.isString(r) && a.push('path=' + r),
                q.isString(o) && a.push('domain=' + o),
                !0 === i && a.push('secure'),
                (document.cookie = a.join('; ')));
            },
            read: function (e) {
              var t = document.cookie.match(new RegExp('(^|;\\s*)(' + e + ')=([^;]*)'));
              return t ? decodeURIComponent(t[3]) : null;
            },
            remove: function (e) {
              this.write(e, '', Date.now() - 864e5);
            },
          }
        : {
            write: function () {},
            read: function () {
              return null;
            },
            remove: function () {},
          };
      function ge(e, t) {
        return e && !/^([a-z][a-z\d+\-.]*:)?\/\//i.test(t)
          ? (function (e, t) {
              return t ? e.replace(/\/+$/, '') + '/' + t.replace(/^\/+/, '') : e;
            })(e, t)
          : t;
      }
      var we = re.isStandardBrowserEnv
        ? (function () {
            var e,
              t = /(msie|trident)/i.test(navigator.userAgent),
              n = document.createElement('a');
            function r(e) {
              var r = e;
              return (
                t && (n.setAttribute('href', r), (r = n.href)),
                n.setAttribute('href', r),
                {
                  href: n.href,
                  protocol: n.protocol ? n.protocol.replace(/:$/, '') : '',
                  host: n.host,
                  search: n.search ? n.search.replace(/^\?/, '') : '',
                  hash: n.hash ? n.hash.replace(/^#/, '') : '',
                  hostname: n.hostname,
                  port: n.port,
                  pathname: '/' === n.pathname.charAt(0) ? n.pathname : '/' + n.pathname,
                }
              );
            }
            return (
              (e = r(window.location.href)),
              function (t) {
                var n = q.isString(t) ? r(t) : t;
                return n.protocol === e.protocol && n.host === e.host;
              }
            );
          })()
        : function () {
            return !0;
          };
      function Ee(e, t) {
        var n = 0,
          r = (function (e, t) {
            e = e || 10;
            var n,
              r = new Array(e),
              o = new Array(e),
              i = 0,
              a = 0;
            return (
              (t = void 0 !== t ? t : 1e3),
              function (s) {
                var u = Date.now(),
                  c = o[a];
                (n || (n = u), (r[i] = s), (o[i] = u));
                for (var f = a, l = 0; f !== i; ) ((l += r[f++]), (f %= e));
                if (((i = (i + 1) % e) === a && (a = (a + 1) % e), !(u - n < t))) {
                  var d = c && u - c;
                  return d ? Math.round((1e3 * l) / d) : void 0;
                }
              }
            );
          })(50, 250);
        return function (o) {
          var i = o.loaded,
            a = o.lengthComputable ? o.total : void 0,
            s = i - n,
            u = r(s);
          n = i;
          var c = {
            loaded: i,
            total: a,
            progress: a ? i / a : void 0,
            bytes: s,
            rate: u || void 0,
            estimated: u && a && i <= a ? (a - i) / u : void 0,
            event: o,
          };
          ((c[t ? 'download' : 'upload'] = !0), e(c));
        };
      }
      var Oe = {
        http: null,
        xhr:
          'undefined' != typeof XMLHttpRequest &&
          function (e) {
            return new Promise(function (t, n) {
              var r,
                o = e.data,
                i = he.from(e.headers).normalize(),
                a = e.responseType;
              function s() {
                (e.cancelToken && e.cancelToken.unsubscribe(r), e.signal && e.signal.removeEventListener('abort', r));
              }
              q.isFormData(o) &&
                (re.isStandardBrowserEnv || re.isStandardBrowserWebWorkerEnv
                  ? i.setContentType(!1)
                  : i.setContentType('multipart/form-data;', !1));
              var u = new XMLHttpRequest();
              if (e.auth) {
                var c = e.auth.username || '',
                  f = e.auth.password ? unescape(encodeURIComponent(e.auth.password)) : '';
                i.set('Authorization', 'Basic ' + btoa(c + ':' + f));
              }
              var l = ge(e.baseURL, e.url);
              function d() {
                if (u) {
                  var r = he.from('getAllResponseHeaders' in u && u.getAllResponseHeaders());
                  (!(function (e, t, n) {
                    var r = n.config.validateStatus;
                    n.status && r && !r(n.status)
                      ? t(
                          new M(
                            'Request failed with status code ' + n.status,
                            [M.ERR_BAD_REQUEST, M.ERR_BAD_RESPONSE][Math.floor(n.status / 100) - 4],
                            n.config,
                            n.request,
                            n,
                          ),
                        )
                      : e(n);
                  })(
                    function (e) {
                      (t(e), s());
                    },
                    function (e) {
                      (n(e), s());
                    },
                    {
                      data: a && 'text' !== a && 'json' !== a ? u.response : u.responseText,
                      status: u.status,
                      statusText: u.statusText,
                      headers: r,
                      config: e,
                      request: u,
                    },
                  ),
                    (u = null));
                }
              }
              if (
                (u.open(e.method.toUpperCase(), Y(l, e.params, e.paramsSerializer), !0),
                (u.timeout = e.timeout),
                'onloadend' in u
                  ? (u.onloadend = d)
                  : (u.onreadystatechange = function () {
                      u &&
                        4 === u.readyState &&
                        (0 !== u.status || (u.responseURL && 0 === u.responseURL.indexOf('file:'))) &&
                        setTimeout(d);
                    }),
                (u.onabort = function () {
                  u && (n(new M('Request aborted', M.ECONNABORTED, e, u)), (u = null));
                }),
                (u.onerror = function () {
                  (n(new M('Network Error', M.ERR_NETWORK, e, u)), (u = null));
                }),
                (u.ontimeout = function () {
                  var t = e.timeout ? 'timeout of ' + e.timeout + 'ms exceeded' : 'timeout exceeded',
                    r = e.transitional || ne;
                  (e.timeoutErrorMessage && (t = e.timeoutErrorMessage),
                    n(new M(t, r.clarifyTimeoutError ? M.ETIMEDOUT : M.ECONNABORTED, e, u)),
                    (u = null));
                }),
                re.isStandardBrowserEnv)
              ) {
                var p = (e.withCredentials || we(l)) && e.xsrfCookieName && be.read(e.xsrfCookieName);
                p && i.set(e.xsrfHeaderName, p);
              }
              (void 0 === o && i.setContentType(null),
                'setRequestHeader' in u &&
                  q.forEach(i.toJSON(), function (e, t) {
                    u.setRequestHeader(t, e);
                  }),
                q.isUndefined(e.withCredentials) || (u.withCredentials = !!e.withCredentials),
                a && 'json' !== a && (u.responseType = e.responseType),
                'function' == typeof e.onDownloadProgress &&
                  u.addEventListener('progress', Ee(e.onDownloadProgress, !0)),
                'function' == typeof e.onUploadProgress &&
                  u.upload &&
                  u.upload.addEventListener('progress', Ee(e.onUploadProgress)),
                (e.cancelToken || e.signal) &&
                  ((r = function (t) {
                    u && (n(!t || t.type ? new ve(null, e, u) : t), u.abort(), (u = null));
                  }),
                  e.cancelToken && e.cancelToken.subscribe(r),
                  e.signal && (e.signal.aborted ? r() : e.signal.addEventListener('abort', r))));
              var h,
                m = ((h = /^([-+\w]{1,25})(:?\/\/|:)/.exec(l)) && h[1]) || '';
              m && -1 === re.protocols.indexOf(m)
                ? n(new M('Unsupported protocol ' + m + ':', M.ERR_BAD_REQUEST, e))
                : u.send(o || null);
            });
          },
      };
      q.forEach(Oe, function (e, t) {
        if (e) {
          try {
            Object.defineProperty(e, 'name', { value: t });
          } catch (e) {}
          Object.defineProperty(e, 'adapterName', { value: t });
        }
      });
      var Se = function (e) {
        for (
          var t, n, r = (e = q.isArray(e) ? e : [e]).length, o = 0;
          o < r && ((t = e[o]), !(n = q.isString(t) ? Oe[t.toLowerCase()] : t));
          o++
        );
        if (!n) {
          if (!1 === n) throw new M('Adapter '.concat(t, ' is not supported by the environment'), 'ERR_NOT_SUPPORT');
          throw new Error(
            q.hasOwnProp(Oe, t)
              ? "Adapter '".concat(t, "' is not available in the build")
              : "Unknown adapter '".concat(t, "'"),
          );
        }
        if (!q.isFunction(n)) throw new TypeError('adapter is not a function');
        return n;
      };
      function Re(e) {
        if ((e.cancelToken && e.cancelToken.throwIfRequested(), e.signal && e.signal.aborted)) throw new ve(null, e);
      }
      function Ae(e) {
        return (
          Re(e),
          (e.headers = he.from(e.headers)),
          (e.data = me.call(e, e.transformRequest)),
          -1 !== ['post', 'put', 'patch'].indexOf(e.method) &&
            e.headers.setContentType('application/x-www-form-urlencoded', !1),
          Se(e.adapter || se.adapter)(e).then(
            function (t) {
              return (Re(e), (t.data = me.call(e, e.transformResponse, t)), (t.headers = he.from(t.headers)), t);
            },
            function (t) {
              return (
                ye(t) ||
                  (Re(e),
                  t &&
                    t.response &&
                    ((t.response.data = me.call(e, e.transformResponse, t.response)),
                    (t.response.headers = he.from(t.response.headers)))),
                Promise.reject(t)
              );
            },
          )
        );
      }
      var Te = function (e) {
        return e instanceof he ? e.toJSON() : e;
      };
      function je(e, t) {
        t = t || {};
        var n = {};
        function r(e, t, n) {
          return q.isPlainObject(e) && q.isPlainObject(t)
            ? q.merge.call({ caseless: n }, e, t)
            : q.isPlainObject(t)
              ? q.merge({}, t)
              : q.isArray(t)
                ? t.slice()
                : t;
        }
        function o(e, t, n) {
          return q.isUndefined(t) ? (q.isUndefined(e) ? void 0 : r(void 0, e, n)) : r(e, t, n);
        }
        function i(e, t) {
          if (!q.isUndefined(t)) return r(void 0, t);
        }
        function a(e, t) {
          return q.isUndefined(t) ? (q.isUndefined(e) ? void 0 : r(void 0, e)) : r(void 0, t);
        }
        function s(n, o, i) {
          return i in t ? r(n, o) : i in e ? r(void 0, n) : void 0;
        }
        var u = {
          url: i,
          method: i,
          data: i,
          baseURL: a,
          transformRequest: a,
          transformResponse: a,
          paramsSerializer: a,
          timeout: a,
          timeoutMessage: a,
          withCredentials: a,
          adapter: a,
          responseType: a,
          xsrfCookieName: a,
          xsrfHeaderName: a,
          onUploadProgress: a,
          onDownloadProgress: a,
          decompress: a,
          maxContentLength: a,
          maxBodyLength: a,
          beforeRedirect: a,
          transport: a,
          httpAgent: a,
          httpsAgent: a,
          cancelToken: a,
          socketPath: a,
          responseEncoding: a,
          validateStatus: s,
          headers: function (e, t) {
            return o(Te(e), Te(t), !0);
          },
        };
        return (
          q.forEach(Object.keys(Object.assign({}, e, t)), function (r) {
            var i = u[r] || o,
              a = i(e[r], t[r], r);
            (q.isUndefined(a) && i !== s) || (n[r] = a);
          }),
          n
        );
      }
      var Ne = '1.4.0',
        Ce = {};
      ['object', 'boolean', 'number', 'function', 'string', 'symbol'].forEach(function (t, n) {
        Ce[t] = function (r) {
          return e(r) === t || 'a' + (n < 1 ? 'n ' : ' ') + t;
        };
      });
      var xe = {};
      Ce.transitional = function (e, t, n) {
        function r(e, t) {
          return "[Axios v1.4.0] Transitional option '" + e + "'" + t + (n ? '. ' + n : '');
        }
        return function (n, o, i) {
          if (!1 === e) throw new M(r(o, ' has been removed' + (t ? ' in ' + t : '')), M.ERR_DEPRECATED);
          return (
            t &&
              !xe[o] &&
              ((xe[o] = !0),
              console.warn(r(o, ' has been deprecated since v' + t + ' and will be removed in the near future'))),
            !e || e(n, o, i)
          );
        };
      };
      var Pe = {
          assertOptions: function (t, n, r) {
            if ('object' !== e(t)) throw new M('options must be an object', M.ERR_BAD_OPTION_VALUE);
            for (var o = Object.keys(t), i = o.length; i-- > 0; ) {
              var a = o[i],
                s = n[a];
              if (s) {
                var u = t[a],
                  c = void 0 === u || s(u, a, t);
                if (!0 !== c) throw new M('option ' + a + ' must be ' + c, M.ERR_BAD_OPTION_VALUE);
              } else if (!0 !== r) throw new M('Unknown option ' + a, M.ERR_BAD_OPTION);
            }
          },
          validators: Ce,
        },
        ke = Pe.validators,
        Ue = (function () {
          function e(n) {
            (t(this, e), (this.defaults = n), (this.interceptors = { request: new te(), response: new te() }));
          }
          return (
            r(e, [
              {
                key: 'request',
                value: function (e, t) {
                  'string' == typeof e ? ((t = t || {}).url = e) : (t = e || {});
                  var n,
                    r = (t = je(this.defaults, t)),
                    o = r.transitional,
                    i = r.paramsSerializer,
                    a = r.headers;
                  (void 0 !== o &&
                    Pe.assertOptions(
                      o,
                      {
                        silentJSONParsing: ke.transitional(ke.boolean),
                        forcedJSONParsing: ke.transitional(ke.boolean),
                        clarifyTimeoutError: ke.transitional(ke.boolean),
                      },
                      !1,
                    ),
                    null != i &&
                      (q.isFunction(i)
                        ? (t.paramsSerializer = { serialize: i })
                        : Pe.assertOptions(i, { encode: ke.function, serialize: ke.function }, !0)),
                    (t.method = (t.method || this.defaults.method || 'get').toLowerCase()),
                    (n = a && q.merge(a.common, a[t.method])) &&
                      q.forEach(['delete', 'get', 'head', 'post', 'put', 'patch', 'common'], function (e) {
                        delete a[e];
                      }),
                    (t.headers = he.concat(n, a)));
                  var s = [],
                    u = !0;
                  this.interceptors.request.forEach(function (e) {
                    ('function' == typeof e.runWhen && !1 === e.runWhen(t)) ||
                      ((u = u && e.synchronous), s.unshift(e.fulfilled, e.rejected));
                  });
                  var c,
                    f = [];
                  this.interceptors.response.forEach(function (e) {
                    f.push(e.fulfilled, e.rejected);
                  });
                  var l,
                    d = 0;
                  if (!u) {
                    var p = [Ae.bind(this), void 0];
                    for (p.unshift.apply(p, s), p.push.apply(p, f), l = p.length, c = Promise.resolve(t); d < l; )
                      c = c.then(p[d++], p[d++]);
                    return c;
                  }
                  l = s.length;
                  var h = t;
                  for (d = 0; d < l; ) {
                    var m = s[d++],
                      y = s[d++];
                    try {
                      h = m(h);
                    } catch (e) {
                      y.call(this, e);
                      break;
                    }
                  }
                  try {
                    c = Ae.call(this, h);
                  } catch (e) {
                    return Promise.reject(e);
                  }
                  for (d = 0, l = f.length; d < l; ) c = c.then(f[d++], f[d++]);
                  return c;
                },
              },
              {
                key: 'getUri',
                value: function (e) {
                  return Y(ge((e = je(this.defaults, e)).baseURL, e.url), e.params, e.paramsSerializer);
                },
              },
            ]),
            e
          );
        })();
      (q.forEach(['delete', 'get', 'head', 'options'], function (e) {
        Ue.prototype[e] = function (t, n) {
          return this.request(je(n || {}, { method: e, url: t, data: (n || {}).data }));
        };
      }),
        q.forEach(['post', 'put', 'patch'], function (e) {
          function t(t) {
            return function (n, r, o) {
              return this.request(
                je(o || {}, {
                  method: e,
                  headers: t ? { 'Content-Type': 'multipart/form-data' } : {},
                  url: n,
                  data: r,
                }),
              );
            };
          }
          ((Ue.prototype[e] = t()), (Ue.prototype[e + 'Form'] = t(!0)));
        }));
      var _e = Ue,
        Fe = (function () {
          function e(n) {
            if ((t(this, e), 'function' != typeof n)) throw new TypeError('executor must be a function.');
            var r;
            this.promise = new Promise(function (e) {
              r = e;
            });
            var o = this;
            (this.promise.then(function (e) {
              if (o._listeners) {
                for (var t = o._listeners.length; t-- > 0; ) o._listeners[t](e);
                o._listeners = null;
              }
            }),
              (this.promise.then = function (e) {
                var t,
                  n = new Promise(function (e) {
                    (o.subscribe(e), (t = e));
                  }).then(e);
                return (
                  (n.cancel = function () {
                    o.unsubscribe(t);
                  }),
                  n
                );
              }),
              n(function (e, t, n) {
                o.reason || ((o.reason = new ve(e, t, n)), r(o.reason));
              }));
          }
          return (
            r(
              e,
              [
                {
                  key: 'throwIfRequested',
                  value: function () {
                    if (this.reason) throw this.reason;
                  },
                },
                {
                  key: 'subscribe',
                  value: function (e) {
                    this.reason ? e(this.reason) : this._listeners ? this._listeners.push(e) : (this._listeners = [e]);
                  },
                },
                {
                  key: 'unsubscribe',
                  value: function (e) {
                    if (this._listeners) {
                      var t = this._listeners.indexOf(e);
                      -1 !== t && this._listeners.splice(t, 1);
                    }
                  },
                },
              ],
              [
                {
                  key: 'source',
                  value: function () {
                    var t;
                    return {
                      token: new e(function (e) {
                        t = e;
                      }),
                      cancel: t,
                    };
                  },
                },
              ],
            ),
            e
          );
        })();
      var Be = {
        Continue: 100,
        SwitchingProtocols: 101,
        Processing: 102,
        EarlyHints: 103,
        Ok: 200,
        Created: 201,
        Accepted: 202,
        NonAuthoritativeInformation: 203,
        NoContent: 204,
        ResetContent: 205,
        PartialContent: 206,
        MultiStatus: 207,
        AlreadyReported: 208,
        ImUsed: 226,
        MultipleChoices: 300,
        MovedPermanently: 301,
        Found: 302,
        SeeOther: 303,
        NotModified: 304,
        UseProxy: 305,
        Unused: 306,
        TemporaryRedirect: 307,
        PermanentRedirect: 308,
        BadRequest: 400,
        Unauthorized: 401,
        PaymentRequired: 402,
        Forbidden: 403,
        NotFound: 404,
        MethodNotAllowed: 405,
        NotAcceptable: 406,
        ProxyAuthenticationRequired: 407,
        RequestTimeout: 408,
        Conflict: 409,
        Gone: 410,
        LengthRequired: 411,
        PreconditionFailed: 412,
        PayloadTooLarge: 413,
        UriTooLong: 414,
        UnsupportedMediaType: 415,
        RangeNotSatisfiable: 416,
        ExpectationFailed: 417,
        ImATeapot: 418,
        MisdirectedRequest: 421,
        UnprocessableEntity: 422,
        Locked: 423,
        FailedDependency: 424,
        TooEarly: 425,
        UpgradeRequired: 426,
        PreconditionRequired: 428,
        TooManyRequests: 429,
        RequestHeaderFieldsTooLarge: 431,
        UnavailableForLegalReasons: 451,
        InternalServerError: 500,
        NotImplemented: 501,
        BadGateway: 502,
        ServiceUnavailable: 503,
        GatewayTimeout: 504,
        HttpVersionNotSupported: 505,
        VariantAlsoNegotiates: 506,
        InsufficientStorage: 507,
        LoopDetected: 508,
        NotExtended: 510,
        NetworkAuthenticationRequired: 511,
      };
      Object.entries(Be).forEach(function (e) {
        var t = o(e, 2),
          n = t[0],
          r = t[1];
        Be[r] = n;
      });
      var Le = Be;
      var De = (function e(t) {
        var n = new _e(t),
          r = a(_e.prototype.request, n);
        return (
          q.extend(r, _e.prototype, n, { allOwnKeys: !0 }),
          q.extend(r, n, null, { allOwnKeys: !0 }),
          (r.create = function (n) {
            return e(je(t, n));
          }),
          r
        );
      })(se);
      return (
        (De.Axios = _e),
        (De.CanceledError = ve),
        (De.CancelToken = Fe),
        (De.isCancel = ye),
        (De.VERSION = Ne),
        (De.toFormData = G),
        (De.AxiosError = M),
        (De.Cancel = De.CanceledError),
        (De.all = function (e) {
          return Promise.all(e);
        }),
        (De.spread = function (e) {
          return function (t) {
            return e.apply(null, t);
          };
        }),
        (De.isAxiosError = function (e) {
          return q.isObject(e) && !0 === e.isAxiosError;
        }),
        (De.mergeConfig = je),
        (De.AxiosHeaders = he),
        (De.formToJSON = function (e) {
          return oe(q.isHTMLForm(e) ? new FormData(e) : e);
        }),
        (De.HttpStatusCode = Le),
        (De.default = De),
        De
      );
    });
    return {
      requestAction: function (me, action, config) {
        config.url = me.getActionUrl();
        config.method = 'post';
        config.params = config.params || {};
        config.params = Object.assign(config.params, me.getOpt('serverparam'));
        config.params.action = action;
        return this.request(me, config);
      },
      request: function (me, config) {
        config.headers = config.headers || {};
        var customHeaders = me.getOpt('serverHeaders');
        if (customHeaders) {
          for (var key in customHeaders) {
            config.headers[key] = customHeaders[key];
          }
        }
        return axios(config);
      },
    };
  })();
  UE.image = (function () {
    var imageCompression = null;
    !(function (e, t) {
      imageCompression = t();
    })(this, function () {
      'use strict';
      function _mergeNamespaces(e, t) {
        return (
          t.forEach(function (t) {
            t &&
              'string' != typeof t &&
              !Array.isArray(t) &&
              Object.keys(t).forEach(function (r) {
                if ('default' !== r && !(r in e)) {
                  var i = Object.getOwnPropertyDescriptor(t, r);
                  Object.defineProperty(
                    e,
                    r,
                    i.get
                      ? i
                      : {
                          enumerable: !0,
                          get: function () {
                            return t[r];
                          },
                        },
                  );
                }
              });
          }),
          Object.freeze(e)
        );
      }
      function copyExifWithoutOrientation(e, t) {
        return new Promise(function (r, i) {
          let o;
          return getApp1Segment(e).then(function (e) {
            try {
              return ((o = e), r(new Blob([t.slice(0, 2), o, t.slice(2)], { type: 'image/jpeg' })));
            } catch (e) {
              return i(e);
            }
          }, i);
        });
      }
      const getApp1Segment = (e) =>
        new Promise((t, r) => {
          const i = new FileReader();
          (i.addEventListener('load', ({ target: { result: e } }) => {
            const i = new DataView(e);
            let o = 0;
            if (65496 !== i.getUint16(o)) return r('not a valid JPEG');
            for (o += 2; ; ) {
              const a = i.getUint16(o);
              if (65498 === a) break;
              const s = i.getUint16(o + 2);
              if (65505 === a && 1165519206 === i.getUint32(o + 4)) {
                const a = o + 10;
                let f;
                switch (i.getUint16(a)) {
                  case 18761:
                    f = !0;
                    break;
                  case 19789:
                    f = !1;
                    break;
                  default:
                    return r('TIFF header contains invalid endian');
                }
                if (42 !== i.getUint16(a + 2, f)) return r('TIFF header contains invalid version');
                const l = i.getUint32(a + 4, f),
                  c = a + l + 2 + 12 * i.getUint16(a + l, f);
                for (let e = a + l + 2; e < c; e += 12) {
                  if (274 == i.getUint16(e, f)) {
                    if (3 !== i.getUint16(e + 2, f)) return r('Orientation data type is invalid');
                    if (1 !== i.getUint32(e + 4, f)) return r('Orientation data count is invalid');
                    i.setUint16(e + 8, 1, f);
                    break;
                  }
                }
                return t(e.slice(o, o + 2 + s));
              }
              o += 2 + s;
            }
            return t(new Blob());
          }),
            i.readAsArrayBuffer(e));
        });
      var e = {};
      !(function (e) {
        var t,
          r,
          UZIP = {};
        ((e.exports = UZIP),
          (UZIP.parse = function (e, t) {
            for (
              var r = UZIP.bin.readUshort,
                i = UZIP.bin.readUint,
                o = 0,
                a = {},
                s = new Uint8Array(e),
                f = s.length - 4;
              101010256 != i(s, f);

            )
              f--;
            o = f;
            o += 4;
            var l = r(s, (o += 4));
            r(s, (o += 2));
            var c = i(s, (o += 2)),
              u = i(s, (o += 4));
            ((o += 4), (o = u));
            for (var h = 0; h < l; h++) {
              (i(s, o), (o += 4), (o += 4), (o += 4), i(s, (o += 4)));
              c = i(s, (o += 4));
              var d = i(s, (o += 4)),
                A = r(s, (o += 4)),
                g = r(s, o + 2),
                p = r(s, o + 4);
              o += 6;
              var m = i(s, (o += 8));
              ((o += 4), (o += A + g + p), UZIP._readLocal(s, m, a, c, d, t));
            }
            return a;
          }),
          (UZIP._readLocal = function (e, t, r, i, o, a) {
            var s = UZIP.bin.readUshort,
              f = UZIP.bin.readUint;
            (f(e, t), s(e, (t += 4)), s(e, (t += 2)));
            var l = s(e, (t += 2));
            (f(e, (t += 2)), f(e, (t += 4)), (t += 4));
            var c = s(e, (t += 8)),
              u = s(e, (t += 2));
            t += 2;
            var h = UZIP.bin.readUTF8(e, t, c);
            if (((t += c), (t += u), a)) r[h] = { size: o, csize: i };
            else {
              var d = new Uint8Array(e.buffer, t);
              if (0 == l) r[h] = new Uint8Array(d.buffer.slice(t, t + i));
              else {
                if (8 != l) throw 'unknown compression method: ' + l;
                var A = new Uint8Array(o);
                (UZIP.inflateRaw(d, A), (r[h] = A));
              }
            }
          }),
          (UZIP.inflateRaw = function (e, t) {
            return UZIP.F.inflate(e, t);
          }),
          (UZIP.inflate = function (e, t) {
            return (e[0], e[1], UZIP.inflateRaw(new Uint8Array(e.buffer, e.byteOffset + 2, e.length - 6), t));
          }),
          (UZIP.deflate = function (e, t) {
            null == t && (t = { level: 6 });
            var r = 0,
              i = new Uint8Array(50 + Math.floor(1.1 * e.length));
            ((i[r] = 120), (i[r + 1] = 156), (r += 2), (r = UZIP.F.deflateRaw(e, i, r, t.level)));
            var o = UZIP.adler(e, 0, e.length);
            return (
              (i[r + 0] = (o >>> 24) & 255),
              (i[r + 1] = (o >>> 16) & 255),
              (i[r + 2] = (o >>> 8) & 255),
              (i[r + 3] = (o >>> 0) & 255),
              new Uint8Array(i.buffer, 0, r + 4)
            );
          }),
          (UZIP.deflateRaw = function (e, t) {
            null == t && (t = { level: 6 });
            var r = new Uint8Array(50 + Math.floor(1.1 * e.length)),
              i = UZIP.F.deflateRaw(e, r, i, t.level);
            return new Uint8Array(r.buffer, 0, i);
          }),
          (UZIP.encode = function (e, t) {
            null == t && (t = !1);
            var r = 0,
              i = UZIP.bin.writeUint,
              o = UZIP.bin.writeUshort,
              a = {};
            for (var s in e) {
              var f = !UZIP._noNeed(s) && !t,
                l = e[s],
                c = UZIP.crc.crc(l, 0, l.length);
              a[s] = { cpr: f, usize: l.length, crc: c, file: f ? UZIP.deflateRaw(l) : l };
            }
            for (var s in a) r += a[s].file.length + 30 + 46 + 2 * UZIP.bin.sizeUTF8(s);
            r += 22;
            var u = new Uint8Array(r),
              h = 0,
              d = [];
            for (var s in a) {
              var A = a[s];
              (d.push(h), (h = UZIP._writeHeader(u, h, s, A, 0)));
            }
            var g = 0,
              p = h;
            for (var s in a) {
              A = a[s];
              (d.push(h), (h = UZIP._writeHeader(u, h, s, A, 1, d[g++])));
            }
            var m = h - p;
            return (
              i(u, h, 101010256),
              (h += 4),
              o(u, (h += 4), g),
              o(u, (h += 2), g),
              i(u, (h += 2), m),
              i(u, (h += 4), p),
              (h += 4),
              (h += 2),
              u.buffer
            );
          }),
          (UZIP._noNeed = function (e) {
            var t = e.split('.').pop().toLowerCase();
            return -1 != 'png,jpg,jpeg,zip'.indexOf(t);
          }),
          (UZIP._writeHeader = function (e, t, r, i, o, a) {
            var s = UZIP.bin.writeUint,
              f = UZIP.bin.writeUshort,
              l = i.file;
            return (
              s(e, t, 0 == o ? 67324752 : 33639248),
              (t += 4),
              1 == o && (t += 2),
              f(e, t, 20),
              f(e, (t += 2), 0),
              f(e, (t += 2), i.cpr ? 8 : 0),
              s(e, (t += 2), 0),
              s(e, (t += 4), i.crc),
              s(e, (t += 4), l.length),
              s(e, (t += 4), i.usize),
              f(e, (t += 4), UZIP.bin.sizeUTF8(r)),
              f(e, (t += 2), 0),
              (t += 2),
              1 == o && ((t += 2), (t += 2), s(e, (t += 6), a), (t += 4)),
              (t += UZIP.bin.writeUTF8(e, t, r)),
              0 == o && (e.set(l, t), (t += l.length)),
              t
            );
          }),
          (UZIP.crc = {
            table: (function () {
              for (var e = new Uint32Array(256), t = 0; t < 256; t++) {
                for (var r = t, i = 0; i < 8; i++) 1 & r ? (r = 3988292384 ^ (r >>> 1)) : (r >>>= 1);
                e[t] = r;
              }
              return e;
            })(),
            update: function (e, t, r, i) {
              for (var o = 0; o < i; o++) e = UZIP.crc.table[255 & (e ^ t[r + o])] ^ (e >>> 8);
              return e;
            },
            crc: function (e, t, r) {
              return 4294967295 ^ UZIP.crc.update(4294967295, e, t, r);
            },
          }),
          (UZIP.adler = function (e, t, r) {
            for (var i = 1, o = 0, a = t, s = t + r; a < s; ) {
              for (var f = Math.min(a + 5552, s); a < f; ) o += i += e[a++];
              ((i %= 65521), (o %= 65521));
            }
            return (o << 16) | i;
          }),
          (UZIP.bin = {
            readUshort: function (e, t) {
              return e[t] | (e[t + 1] << 8);
            },
            writeUshort: function (e, t, r) {
              ((e[t] = 255 & r), (e[t + 1] = (r >> 8) & 255));
            },
            readUint: function (e, t) {
              return 16777216 * e[t + 3] + ((e[t + 2] << 16) | (e[t + 1] << 8) | e[t]);
            },
            writeUint: function (e, t, r) {
              ((e[t] = 255 & r),
                (e[t + 1] = (r >> 8) & 255),
                (e[t + 2] = (r >> 16) & 255),
                (e[t + 3] = (r >> 24) & 255));
            },
            readASCII: function (e, t, r) {
              for (var i = '', o = 0; o < r; o++) i += String.fromCharCode(e[t + o]);
              return i;
            },
            writeASCII: function (e, t, r) {
              for (var i = 0; i < r.length; i++) e[t + i] = r.charCodeAt(i);
            },
            pad: function (e) {
              return e.length < 2 ? '0' + e : e;
            },
            readUTF8: function (e, t, r) {
              for (var i, o = '', a = 0; a < r; a++) o += '%' + UZIP.bin.pad(e[t + a].toString(16));
              try {
                i = decodeURIComponent(o);
              } catch (i) {
                return UZIP.bin.readASCII(e, t, r);
              }
              return i;
            },
            writeUTF8: function (e, t, r) {
              for (var i = r.length, o = 0, a = 0; a < i; a++) {
                var s = r.charCodeAt(a);
                if (0 == (4294967168 & s)) ((e[t + o] = s), o++);
                else if (0 == (4294965248 & s))
                  ((e[t + o] = 192 | (s >> 6)), (e[t + o + 1] = 128 | ((s >> 0) & 63)), (o += 2));
                else if (0 == (4294901760 & s))
                  ((e[t + o] = 224 | (s >> 12)),
                    (e[t + o + 1] = 128 | ((s >> 6) & 63)),
                    (e[t + o + 2] = 128 | ((s >> 0) & 63)),
                    (o += 3));
                else {
                  if (0 != (4292870144 & s)) throw 'e';
                  ((e[t + o] = 240 | (s >> 18)),
                    (e[t + o + 1] = 128 | ((s >> 12) & 63)),
                    (e[t + o + 2] = 128 | ((s >> 6) & 63)),
                    (e[t + o + 3] = 128 | ((s >> 0) & 63)),
                    (o += 4));
                }
              }
              return o;
            },
            sizeUTF8: function (e) {
              for (var t = e.length, r = 0, i = 0; i < t; i++) {
                var o = e.charCodeAt(i);
                if (0 == (4294967168 & o)) r++;
                else if (0 == (4294965248 & o)) r += 2;
                else if (0 == (4294901760 & o)) r += 3;
                else {
                  if (0 != (4292870144 & o)) throw 'e';
                  r += 4;
                }
              }
              return r;
            },
          }),
          (UZIP.F = {}),
          (UZIP.F.deflateRaw = function (e, t, r, i) {
            var o = [
                [0, 0, 0, 0, 0],
                [4, 4, 8, 4, 0],
                [4, 5, 16, 8, 0],
                [4, 6, 16, 16, 0],
                [4, 10, 16, 32, 0],
                [8, 16, 32, 32, 0],
                [8, 16, 128, 128, 0],
                [8, 32, 128, 256, 0],
                [32, 128, 258, 1024, 1],
                [32, 258, 258, 4096, 1],
              ][i],
              a = UZIP.F.U,
              s = UZIP.F._goodIndex;
            UZIP.F._hash;
            var f = UZIP.F._putsE,
              l = 0,
              c = r << 3,
              u = 0,
              h = e.length;
            if (0 == i) {
              for (; l < h; ) {
                (f(t, c, l + (_ = Math.min(65535, h - l)) == h ? 1 : 0),
                  (c = UZIP.F._copyExact(e, l, _, t, c + 8)),
                  (l += _));
              }
              return c >>> 3;
            }
            var d = a.lits,
              A = a.strt,
              g = a.prev,
              p = 0,
              m = 0,
              w = 0,
              v = 0,
              b = 0,
              y = 0;
            for (h > 2 && (A[(y = UZIP.F._hash(e, 0))] = 0), l = 0; l < h; l++) {
              if (((b = y), l + 1 < h - 2)) {
                y = UZIP.F._hash(e, l + 1);
                var E = (l + 1) & 32767;
                ((g[E] = A[y]), (A[y] = E));
              }
              if (u <= l) {
                (p > 14e3 || m > 26697) &&
                  h - l > 100 &&
                  (u < l && ((d[p] = l - u), (p += 2), (u = l)),
                  (c = UZIP.F._writeBlock(l == h - 1 || u == h ? 1 : 0, d, p, v, e, w, l - w, t, c)),
                  (p = m = v = 0),
                  (w = l));
                var F = 0;
                l < h - 2 && (F = UZIP.F._bestMatch(e, l, g, b, Math.min(o[2], h - l), o[3]));
                var _ = F >>> 16,
                  B = 65535 & F;
                if (0 != F) {
                  B = 65535 & F;
                  var U = s((_ = F >>> 16), a.of0);
                  a.lhst[257 + U]++;
                  var C = s(B, a.df0);
                  (a.dhst[C]++,
                    (v += a.exb[U] + a.dxb[C]),
                    (d[p] = (_ << 23) | (l - u)),
                    (d[p + 1] = (B << 16) | (U << 8) | C),
                    (p += 2),
                    (u = l + _));
                } else a.lhst[e[l]]++;
                m++;
              }
            }
            for (
              (w == l && 0 != e.length) ||
              (u < l && ((d[p] = l - u), (p += 2), (u = l)),
              (c = UZIP.F._writeBlock(1, d, p, v, e, w, l - w, t, c)),
              (p = 0),
              (m = 0),
              (p = m = v = 0),
              (w = l));
              0 != (7 & c);

            )
              c++;
            return c >>> 3;
          }),
          (UZIP.F._bestMatch = function (e, t, r, i, o, a) {
            var s = 32767 & t,
              f = r[s],
              l = (s - f + 32768) & 32767;
            if (f == s || i != UZIP.F._hash(e, t - l)) return 0;
            for (var c = 0, u = 0, h = Math.min(32767, t); l <= h && 0 != --a && f != s; ) {
              if (0 == c || e[t + c] == e[t + c - l]) {
                var d = UZIP.F._howLong(e, t, l);
                if (d > c) {
                  if (((u = l), (c = d) >= o)) break;
                  l + 2 < d && (d = l + 2);
                  for (var A = 0, g = 0; g < d - 2; g++) {
                    var p = (t - l + g + 32768) & 32767,
                      m = (p - r[p] + 32768) & 32767;
                    m > A && ((A = m), (f = p));
                  }
                }
              }
              l += ((s = f) - (f = r[s]) + 32768) & 32767;
            }
            return (c << 16) | u;
          }),
          (UZIP.F._howLong = function (e, t, r) {
            if (e[t] != e[t - r] || e[t + 1] != e[t + 1 - r] || e[t + 2] != e[t + 2 - r]) return 0;
            var i = t,
              o = Math.min(e.length, t + 258);
            for (t += 3; t < o && e[t] == e[t - r]; ) t++;
            return t - i;
          }),
          (UZIP.F._hash = function (e, t) {
            return (((e[t] << 8) | e[t + 1]) + (e[t + 2] << 4)) & 65535;
          }),
          (UZIP.saved = 0),
          (UZIP.F._writeBlock = function (e, t, r, i, o, a, s, f, l) {
            var c,
              u,
              h,
              d,
              A,
              g,
              p,
              m,
              w,
              v = UZIP.F.U,
              b = UZIP.F._putsF,
              y = UZIP.F._putsE;
            (v.lhst[256]++,
              (u = (c = UZIP.F.getTrees())[0]),
              (h = c[1]),
              (d = c[2]),
              (A = c[3]),
              (g = c[4]),
              (p = c[5]),
              (m = c[6]),
              (w = c[7]));
            var E = 32 + (0 == ((l + 3) & 7) ? 0 : 8 - ((l + 3) & 7)) + (s << 3),
              F = i + UZIP.F.contSize(v.fltree, v.lhst) + UZIP.F.contSize(v.fdtree, v.dhst),
              _ = i + UZIP.F.contSize(v.ltree, v.lhst) + UZIP.F.contSize(v.dtree, v.dhst);
            _ += 14 + 3 * p + UZIP.F.contSize(v.itree, v.ihst) + (2 * v.ihst[16] + 3 * v.ihst[17] + 7 * v.ihst[18]);
            for (var B = 0; B < 286; B++) v.lhst[B] = 0;
            for (B = 0; B < 30; B++) v.dhst[B] = 0;
            for (B = 0; B < 19; B++) v.ihst[B] = 0;
            var U = E < F && E < _ ? 0 : F < _ ? 1 : 2;
            if ((b(f, l, e), b(f, l + 1, U), (l += 3), 0 == U)) {
              for (; 0 != (7 & l); ) l++;
              l = UZIP.F._copyExact(o, a, s, f, l);
            } else {
              var C, I;
              if ((1 == U && ((C = v.fltree), (I = v.fdtree)), 2 == U)) {
                (UZIP.F.makeCodes(v.ltree, u),
                  UZIP.F.revCodes(v.ltree, u),
                  UZIP.F.makeCodes(v.dtree, h),
                  UZIP.F.revCodes(v.dtree, h),
                  UZIP.F.makeCodes(v.itree, d),
                  UZIP.F.revCodes(v.itree, d),
                  (C = v.ltree),
                  (I = v.dtree),
                  y(f, l, A - 257),
                  y(f, (l += 5), g - 1),
                  y(f, (l += 5), p - 4),
                  (l += 4));
                for (var Q = 0; Q < p; Q++) y(f, l + 3 * Q, v.itree[1 + (v.ordr[Q] << 1)]);
                ((l += 3 * p), (l = UZIP.F._codeTiny(m, v.itree, f, l)), (l = UZIP.F._codeTiny(w, v.itree, f, l)));
              }
              for (var M = a, x = 0; x < r; x += 2) {
                for (var T = t[x], S = T >>> 23, R = M + (8388607 & T); M < R; ) l = UZIP.F._writeLit(o[M++], C, f, l);
                if (0 != S) {
                  var O = t[x + 1],
                    P = O >> 16,
                    H = (O >> 8) & 255,
                    L = 255 & O;
                  (y(f, (l = UZIP.F._writeLit(257 + H, C, f, l)), S - v.of0[H]),
                    (l += v.exb[H]),
                    b(f, (l = UZIP.F._writeLit(L, I, f, l)), P - v.df0[L]),
                    (l += v.dxb[L]),
                    (M += S));
                }
              }
              l = UZIP.F._writeLit(256, C, f, l);
            }
            return l;
          }),
          (UZIP.F._copyExact = function (e, t, r, i, o) {
            var a = o >>> 3;
            return (
              (i[a] = r),
              (i[a + 1] = r >>> 8),
              (i[a + 2] = 255 - i[a]),
              (i[a + 3] = 255 - i[a + 1]),
              (a += 4),
              i.set(new Uint8Array(e.buffer, t, r), a),
              o + ((r + 4) << 3)
            );
          }),
          (UZIP.F.getTrees = function () {
            for (
              var e = UZIP.F.U,
                t = UZIP.F._hufTree(e.lhst, e.ltree, 15),
                r = UZIP.F._hufTree(e.dhst, e.dtree, 15),
                i = [],
                o = UZIP.F._lenCodes(e.ltree, i),
                a = [],
                s = UZIP.F._lenCodes(e.dtree, a),
                f = 0;
              f < i.length;
              f += 2
            )
              e.ihst[i[f]]++;
            for (f = 0; f < a.length; f += 2) e.ihst[a[f]]++;
            for (var l = UZIP.F._hufTree(e.ihst, e.itree, 7), c = 19; c > 4 && 0 == e.itree[1 + (e.ordr[c - 1] << 1)]; )
              c--;
            return [t, r, l, o, s, c, i, a];
          }),
          (UZIP.F.getSecond = function (e) {
            for (var t = [], r = 0; r < e.length; r += 2) t.push(e[r + 1]);
            return t;
          }),
          (UZIP.F.nonZero = function (e) {
            for (var t = '', r = 0; r < e.length; r += 2) 0 != e[r + 1] && (t += (r >> 1) + ',');
            return t;
          }),
          (UZIP.F.contSize = function (e, t) {
            for (var r = 0, i = 0; i < t.length; i++) r += t[i] * e[1 + (i << 1)];
            return r;
          }),
          (UZIP.F._codeTiny = function (e, t, r, i) {
            for (var o = 0; o < e.length; o += 2) {
              var a = e[o],
                s = e[o + 1];
              i = UZIP.F._writeLit(a, t, r, i);
              var f = 16 == a ? 2 : 17 == a ? 3 : 7;
              a > 15 && (UZIP.F._putsE(r, i, s, f), (i += f));
            }
            return i;
          }),
          (UZIP.F._lenCodes = function (e, t) {
            for (var r = e.length; 2 != r && 0 == e[r - 1]; ) r -= 2;
            for (var i = 0; i < r; i += 2) {
              var o = e[i + 1],
                a = i + 3 < r ? e[i + 3] : -1,
                s = i + 5 < r ? e[i + 5] : -1,
                f = 0 == i ? -1 : e[i - 1];
              if (0 == o && a == o && s == o) {
                for (var l = i + 5; l + 2 < r && e[l + 2] == o; ) l += 2;
                ((c = Math.min((l + 1 - i) >>> 1, 138)) < 11 ? t.push(17, c - 3) : t.push(18, c - 11),
                  (i += 2 * c - 2));
              } else if (o == f && a == o && s == o) {
                for (l = i + 5; l + 2 < r && e[l + 2] == o; ) l += 2;
                var c = Math.min((l + 1 - i) >>> 1, 6);
                (t.push(16, c - 3), (i += 2 * c - 2));
              } else t.push(o, 0);
            }
            return r >>> 1;
          }),
          (UZIP.F._hufTree = function (e, t, r) {
            var i = [],
              o = e.length,
              a = t.length,
              s = 0;
            for (s = 0; s < a; s += 2) ((t[s] = 0), (t[s + 1] = 0));
            for (s = 0; s < o; s++) 0 != e[s] && i.push({ lit: s, f: e[s] });
            var f = i.length,
              l = i.slice(0);
            if (0 == f) return 0;
            if (1 == f) {
              var c = i[0].lit;
              l = 0 == c ? 1 : 0;
              return ((t[1 + (c << 1)] = 1), (t[1 + (l << 1)] = 1), 1);
            }
            i.sort(function (e, t) {
              return e.f - t.f;
            });
            var u = i[0],
              h = i[1],
              d = 0,
              A = 1,
              g = 2;
            for (i[0] = { lit: -1, f: u.f + h.f, l: u, r: h, d: 0 }; A != f - 1; )
              ((u = d != A && (g == f || i[d].f < i[g].f) ? i[d++] : i[g++]),
                (h = d != A && (g == f || i[d].f < i[g].f) ? i[d++] : i[g++]),
                (i[A++] = { lit: -1, f: u.f + h.f, l: u, r: h }));
            var p = UZIP.F.setDepth(i[A - 1], 0);
            for (p > r && (UZIP.F.restrictDepth(l, r, p), (p = r)), s = 0; s < f; s++) t[1 + (l[s].lit << 1)] = l[s].d;
            return p;
          }),
          (UZIP.F.setDepth = function (e, t) {
            return -1 != e.lit ? ((e.d = t), t) : Math.max(UZIP.F.setDepth(e.l, t + 1), UZIP.F.setDepth(e.r, t + 1));
          }),
          (UZIP.F.restrictDepth = function (e, t, r) {
            var i = 0,
              o = 1 << (r - t),
              a = 0;
            for (
              e.sort(function (e, t) {
                return t.d == e.d ? e.f - t.f : t.d - e.d;
              }),
                i = 0;
              i < e.length && e[i].d > t;
              i++
            ) {
              var s = e[i].d;
              ((e[i].d = t), (a += o - (1 << (r - s))));
            }
            for (a >>>= r - t; a > 0; ) {
              (s = e[i].d) < t ? (e[i].d++, (a -= 1 << (t - s - 1))) : i++;
            }
            for (; i >= 0; i--) e[i].d == t && a < 0 && (e[i].d--, a++);
            0 != a && console.log('debt left');
          }),
          (UZIP.F._goodIndex = function (e, t) {
            var r = 0;
            return (
              t[16 | r] <= e && (r |= 16),
              t[8 | r] <= e && (r |= 8),
              t[4 | r] <= e && (r |= 4),
              t[2 | r] <= e && (r |= 2),
              t[1 | r] <= e && (r |= 1),
              r
            );
          }),
          (UZIP.F._writeLit = function (e, t, r, i) {
            return (UZIP.F._putsF(r, i, t[e << 1]), i + t[1 + (e << 1)]);
          }),
          (UZIP.F.inflate = function (e, t) {
            var r = Uint8Array;
            if (3 == e[0] && 0 == e[1]) return t || new r(0);
            var i = UZIP.F,
              o = i._bitsF,
              a = i._bitsE,
              s = i._decodeTiny,
              f = i.makeCodes,
              l = i.codes2map,
              c = i._get17,
              u = i.U,
              h = null == t;
            h && (t = new r((e.length >>> 2) << 3));
            for (var d, A, g = 0, p = 0, m = 0, w = 0, v = 0, b = 0, y = 0, E = 0, F = 0; 0 == g; )
              if (((g = o(e, F, 1)), (p = o(e, F + 1, 2)), (F += 3), 0 != p)) {
                if (
                  (h && (t = UZIP.F._check(t, E + (1 << 17))),
                  1 == p && ((d = u.flmap), (A = u.fdmap), (b = 511), (y = 31)),
                  2 == p)
                ) {
                  ((m = a(e, F, 5) + 257), (w = a(e, F + 5, 5) + 1), (v = a(e, F + 10, 4) + 4), (F += 14));
                  for (var _ = 0; _ < 38; _ += 2) ((u.itree[_] = 0), (u.itree[_ + 1] = 0));
                  var B = 1;
                  for (_ = 0; _ < v; _++) {
                    var U = a(e, F + 3 * _, 3);
                    ((u.itree[1 + (u.ordr[_] << 1)] = U), U > B && (B = U));
                  }
                  ((F += 3 * v),
                    f(u.itree, B),
                    l(u.itree, B, u.imap),
                    (d = u.lmap),
                    (A = u.dmap),
                    (F = s(u.imap, (1 << B) - 1, m + w, e, F, u.ttree)));
                  var C = i._copyOut(u.ttree, 0, m, u.ltree);
                  b = (1 << C) - 1;
                  var I = i._copyOut(u.ttree, m, w, u.dtree);
                  ((y = (1 << I) - 1), f(u.ltree, C), l(u.ltree, C, d), f(u.dtree, I), l(u.dtree, I, A));
                }
                for (;;) {
                  var Q = d[c(e, F) & b];
                  F += 15 & Q;
                  var M = Q >>> 4;
                  if (M >>> 8 == 0) t[E++] = M;
                  else {
                    if (256 == M) break;
                    var x = E + M - 254;
                    if (M > 264) {
                      var T = u.ldef[M - 257];
                      ((x = E + (T >>> 3) + a(e, F, 7 & T)), (F += 7 & T));
                    }
                    var S = A[c(e, F) & y];
                    F += 15 & S;
                    var R = S >>> 4,
                      O = u.ddef[R],
                      P = (O >>> 4) + o(e, F, 15 & O);
                    for (F += 15 & O, h && (t = UZIP.F._check(t, E + (1 << 17))); E < x; )
                      ((t[E] = t[E++ - P]), (t[E] = t[E++ - P]), (t[E] = t[E++ - P]), (t[E] = t[E++ - P]));
                    E = x;
                  }
                }
              } else {
                0 != (7 & F) && (F += 8 - (7 & F));
                var H = 4 + (F >>> 3),
                  L = e[H - 4] | (e[H - 3] << 8);
                (h && (t = UZIP.F._check(t, E + L)),
                  t.set(new r(e.buffer, e.byteOffset + H, L), E),
                  (F = (H + L) << 3),
                  (E += L));
              }
            return t.length == E ? t : t.slice(0, E);
          }),
          (UZIP.F._check = function (e, t) {
            var r = e.length;
            if (t <= r) return e;
            var i = new Uint8Array(Math.max(r << 1, t));
            return (i.set(e, 0), i);
          }),
          (UZIP.F._decodeTiny = function (e, t, r, i, o, a) {
            for (var s = UZIP.F._bitsE, f = UZIP.F._get17, l = 0; l < r; ) {
              var c = e[f(i, o) & t];
              o += 15 & c;
              var u = c >>> 4;
              if (u <= 15) ((a[l] = u), l++);
              else {
                var h = 0,
                  d = 0;
                16 == u
                  ? ((d = 3 + s(i, o, 2)), (o += 2), (h = a[l - 1]))
                  : 17 == u
                    ? ((d = 3 + s(i, o, 3)), (o += 3))
                    : 18 == u && ((d = 11 + s(i, o, 7)), (o += 7));
                for (var A = l + d; l < A; ) ((a[l] = h), l++);
              }
            }
            return o;
          }),
          (UZIP.F._copyOut = function (e, t, r, i) {
            for (var o = 0, a = 0, s = i.length >>> 1; a < r; ) {
              var f = e[a + t];
              ((i[a << 1] = 0), (i[1 + (a << 1)] = f), f > o && (o = f), a++);
            }
            for (; a < s; ) ((i[a << 1] = 0), (i[1 + (a << 1)] = 0), a++);
            return o;
          }),
          (UZIP.F.makeCodes = function (e, t) {
            for (var r, i, o, a, s = UZIP.F.U, f = e.length, l = s.bl_count, c = 0; c <= t; c++) l[c] = 0;
            for (c = 1; c < f; c += 2) l[e[c]]++;
            var u = s.next_code;
            for (r = 0, l[0] = 0, i = 1; i <= t; i++) ((r = (r + l[i - 1]) << 1), (u[i] = r));
            for (o = 0; o < f; o += 2) 0 != (a = e[o + 1]) && ((e[o] = u[a]), u[a]++);
          }),
          (UZIP.F.codes2map = function (e, t, r) {
            for (var i = e.length, o = UZIP.F.U.rev15, a = 0; a < i; a += 2)
              if (0 != e[a + 1])
                for (
                  var s = a >> 1, f = e[a + 1], l = (s << 4) | f, c = t - f, u = e[a] << c, h = u + (1 << c);
                  u != h;

                ) {
                  ((r[o[u] >>> (15 - t)] = l), u++);
                }
          }),
          (UZIP.F.revCodes = function (e, t) {
            for (var r = UZIP.F.U.rev15, i = 15 - t, o = 0; o < e.length; o += 2) {
              var a = e[o] << (t - e[o + 1]);
              e[o] = r[a] >>> i;
            }
          }),
          (UZIP.F._putsE = function (e, t, r) {
            r <<= 7 & t;
            var i = t >>> 3;
            ((e[i] |= r), (e[i + 1] |= r >>> 8));
          }),
          (UZIP.F._putsF = function (e, t, r) {
            r <<= 7 & t;
            var i = t >>> 3;
            ((e[i] |= r), (e[i + 1] |= r >>> 8), (e[i + 2] |= r >>> 16));
          }),
          (UZIP.F._bitsE = function (e, t, r) {
            return ((e[t >>> 3] | (e[1 + (t >>> 3)] << 8)) >>> (7 & t)) & ((1 << r) - 1);
          }),
          (UZIP.F._bitsF = function (e, t, r) {
            return ((e[t >>> 3] | (e[1 + (t >>> 3)] << 8) | (e[2 + (t >>> 3)] << 16)) >>> (7 & t)) & ((1 << r) - 1);
          }),
          (UZIP.F._get17 = function (e, t) {
            return (e[t >>> 3] | (e[1 + (t >>> 3)] << 8) | (e[2 + (t >>> 3)] << 16)) >>> (7 & t);
          }),
          (UZIP.F._get25 = function (e, t) {
            return (
              (e[t >>> 3] | (e[1 + (t >>> 3)] << 8) | (e[2 + (t >>> 3)] << 16) | (e[3 + (t >>> 3)] << 24)) >>> (7 & t)
            );
          }),
          (UZIP.F.U =
            ((t = Uint16Array),
            (r = Uint32Array),
            {
              next_code: new t(16),
              bl_count: new t(16),
              ordr: [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15],
              of0: [
                3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195,
                227, 258, 999, 999, 999,
              ],
              exb: [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0, 0],
              ldef: new t(32),
              df0: [
                1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073,
                4097, 6145, 8193, 12289, 16385, 24577, 65535, 65535,
              ],
              dxb: [
                0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 0, 0,
              ],
              ddef: new r(32),
              flmap: new t(512),
              fltree: [],
              fdmap: new t(32),
              fdtree: [],
              lmap: new t(32768),
              ltree: [],
              ttree: [],
              dmap: new t(32768),
              dtree: [],
              imap: new t(512),
              itree: [],
              rev15: new t(32768),
              lhst: new r(286),
              dhst: new r(30),
              ihst: new r(19),
              lits: new r(15e3),
              strt: new t(65536),
              prev: new t(32768),
            })),
          (function () {
            for (var e = UZIP.F.U, t = 0; t < 32768; t++) {
              var r = t;
              ((r =
                ((4278255360 &
                  (r =
                    ((4042322160 &
                      (r =
                        ((3435973836 & (r = ((2863311530 & r) >>> 1) | ((1431655765 & r) << 1))) >>> 2) |
                        ((858993459 & r) << 2))) >>>
                      4) |
                    ((252645135 & r) << 4))) >>>
                  8) |
                ((16711935 & r) << 8)),
                (e.rev15[t] = ((r >>> 16) | (r << 16)) >>> 17));
            }
            function pushV(e, t, r) {
              for (; 0 != t--; ) e.push(0, r);
            }
            for (t = 0; t < 32; t++)
              ((e.ldef[t] = (e.of0[t] << 3) | e.exb[t]), (e.ddef[t] = (e.df0[t] << 4) | e.dxb[t]));
            (pushV(e.fltree, 144, 8),
              pushV(e.fltree, 112, 9),
              pushV(e.fltree, 24, 7),
              pushV(e.fltree, 8, 8),
              UZIP.F.makeCodes(e.fltree, 9),
              UZIP.F.codes2map(e.fltree, 9, e.flmap),
              UZIP.F.revCodes(e.fltree, 9),
              pushV(e.fdtree, 32, 5),
              UZIP.F.makeCodes(e.fdtree, 5),
              UZIP.F.codes2map(e.fdtree, 5, e.fdmap),
              UZIP.F.revCodes(e.fdtree, 5),
              pushV(e.itree, 19, 0),
              pushV(e.ltree, 286, 0),
              pushV(e.dtree, 30, 0),
              pushV(e.ttree, 320, 0));
          })());
      })({
        get exports() {
          return e;
        },
        set exports(t) {
          e = t;
        },
      });
      var UZIP = _mergeNamespaces({ __proto__: null, default: e }, [e]);
      const UPNG = (function () {
        var e = {
          nextZero(e, t) {
            for (; 0 != e[t]; ) t++;
            return t;
          },
          readUshort: (e, t) => (e[t] << 8) | e[t + 1],
          writeUshort(e, t, r) {
            ((e[t] = (r >> 8) & 255), (e[t + 1] = 255 & r));
          },
          readUint: (e, t) => 16777216 * e[t] + ((e[t + 1] << 16) | (e[t + 2] << 8) | e[t + 3]),
          writeUint(e, t, r) {
            ((e[t] = (r >> 24) & 255), (e[t + 1] = (r >> 16) & 255), (e[t + 2] = (r >> 8) & 255), (e[t + 3] = 255 & r));
          },
          readASCII(e, t, r) {
            let i = '';
            for (let o = 0; o < r; o++) i += String.fromCharCode(e[t + o]);
            return i;
          },
          writeASCII(e, t, r) {
            for (let i = 0; i < r.length; i++) e[t + i] = r.charCodeAt(i);
          },
          readBytes(e, t, r) {
            const i = [];
            for (let o = 0; o < r; o++) i.push(e[t + o]);
            return i;
          },
          pad: (e) => (e.length < 2 ? `0${e}` : e),
          readUTF8(t, r, i) {
            let o,
              a = '';
            for (let o = 0; o < i; o++) a += `%${e.pad(t[r + o].toString(16))}`;
            try {
              o = decodeURIComponent(a);
            } catch (o) {
              return e.readASCII(t, r, i);
            }
            return o;
          },
        };
        function decodeImage(t, r, i, o) {
          const a = r * i,
            s = _getBPP(o),
            f = Math.ceil((r * s) / 8),
            l = new Uint8Array(4 * a),
            c = new Uint32Array(l.buffer),
            { ctype: u } = o,
            { depth: h } = o,
            d = e.readUshort;
          if (6 == u) {
            const e = a << 2;
            if (8 == h)
              for (var A = 0; A < e; A += 4)
                ((l[A] = t[A]), (l[A + 1] = t[A + 1]), (l[A + 2] = t[A + 2]), (l[A + 3] = t[A + 3]));
            if (16 == h) for (A = 0; A < e; A++) l[A] = t[A << 1];
          } else if (2 == u) {
            const e = o.tabs.tRNS;
            if (null == e) {
              if (8 == h)
                for (A = 0; A < a; A++) {
                  var g = 3 * A;
                  c[A] = (255 << 24) | (t[g + 2] << 16) | (t[g + 1] << 8) | t[g];
                }
              if (16 == h)
                for (A = 0; A < a; A++) {
                  g = 6 * A;
                  c[A] = (255 << 24) | (t[g + 4] << 16) | (t[g + 2] << 8) | t[g];
                }
            } else {
              var p = e[0];
              const r = e[1],
                i = e[2];
              if (8 == h)
                for (A = 0; A < a; A++) {
                  var m = A << 2;
                  g = 3 * A;
                  ((c[A] = (255 << 24) | (t[g + 2] << 16) | (t[g + 1] << 8) | t[g]),
                    t[g] == p && t[g + 1] == r && t[g + 2] == i && (l[m + 3] = 0));
                }
              if (16 == h)
                for (A = 0; A < a; A++) {
                  ((m = A << 2), (g = 6 * A));
                  ((c[A] = (255 << 24) | (t[g + 4] << 16) | (t[g + 2] << 8) | t[g]),
                    d(t, g) == p && d(t, g + 2) == r && d(t, g + 4) == i && (l[m + 3] = 0));
                }
            }
          } else if (3 == u) {
            const e = o.tabs.PLTE,
              s = o.tabs.tRNS,
              c = s ? s.length : 0;
            if (1 == h)
              for (var w = 0; w < i; w++) {
                var v = w * f,
                  b = w * r;
                for (A = 0; A < r; A++) {
                  m = (b + A) << 2;
                  var y = 3 * (E = (t[v + (A >> 3)] >> (7 - ((7 & A) << 0))) & 1);
                  ((l[m] = e[y]), (l[m + 1] = e[y + 1]), (l[m + 2] = e[y + 2]), (l[m + 3] = E < c ? s[E] : 255));
                }
              }
            if (2 == h)
              for (w = 0; w < i; w++)
                for (v = w * f, b = w * r, A = 0; A < r; A++) {
                  ((m = (b + A) << 2), (y = 3 * (E = (t[v + (A >> 2)] >> (6 - ((3 & A) << 1))) & 3)));
                  ((l[m] = e[y]), (l[m + 1] = e[y + 1]), (l[m + 2] = e[y + 2]), (l[m + 3] = E < c ? s[E] : 255));
                }
            if (4 == h)
              for (w = 0; w < i; w++)
                for (v = w * f, b = w * r, A = 0; A < r; A++) {
                  ((m = (b + A) << 2), (y = 3 * (E = (t[v + (A >> 1)] >> (4 - ((1 & A) << 2))) & 15)));
                  ((l[m] = e[y]), (l[m + 1] = e[y + 1]), (l[m + 2] = e[y + 2]), (l[m + 3] = E < c ? s[E] : 255));
                }
            if (8 == h)
              for (A = 0; A < a; A++) {
                var E;
                ((m = A << 2), (y = 3 * (E = t[A])));
                ((l[m] = e[y]), (l[m + 1] = e[y + 1]), (l[m + 2] = e[y + 2]), (l[m + 3] = E < c ? s[E] : 255));
              }
          } else if (4 == u) {
            if (8 == h)
              for (A = 0; A < a; A++) {
                m = A << 2;
                var F = t[(_ = A << 1)];
                ((l[m] = F), (l[m + 1] = F), (l[m + 2] = F), (l[m + 3] = t[_ + 1]));
              }
            if (16 == h)
              for (A = 0; A < a; A++) {
                var _;
                ((m = A << 2), (F = t[(_ = A << 2)]));
                ((l[m] = F), (l[m + 1] = F), (l[m + 2] = F), (l[m + 3] = t[_ + 2]));
              }
          } else if (0 == u)
            for (p = o.tabs.tRNS ? o.tabs.tRNS : -1, w = 0; w < i; w++) {
              const e = w * f,
                i = w * r;
              if (1 == h)
                for (var B = 0; B < r; B++) {
                  var U = (F = 255 * ((t[e + (B >>> 3)] >>> (7 - (7 & B))) & 1)) == 255 * p ? 0 : 255;
                  c[i + B] = (U << 24) | (F << 16) | (F << 8) | F;
                }
              else if (2 == h)
                for (B = 0; B < r; B++) {
                  U = (F = 85 * ((t[e + (B >>> 2)] >>> (6 - ((3 & B) << 1))) & 3)) == 85 * p ? 0 : 255;
                  c[i + B] = (U << 24) | (F << 16) | (F << 8) | F;
                }
              else if (4 == h)
                for (B = 0; B < r; B++) {
                  U = (F = 17 * ((t[e + (B >>> 1)] >>> (4 - ((1 & B) << 2))) & 15)) == 17 * p ? 0 : 255;
                  c[i + B] = (U << 24) | (F << 16) | (F << 8) | F;
                }
              else if (8 == h)
                for (B = 0; B < r; B++) {
                  U = (F = t[e + B]) == p ? 0 : 255;
                  c[i + B] = (U << 24) | (F << 16) | (F << 8) | F;
                }
              else if (16 == h)
                for (B = 0; B < r; B++) {
                  ((F = t[e + (B << 1)]), (U = d(t, e + (B << 1)) == p ? 0 : 255));
                  c[i + B] = (U << 24) | (F << 16) | (F << 8) | F;
                }
            }
          return l;
        }
        function _decompress(e, r, i, o) {
          const a = _getBPP(e),
            s = Math.ceil((i * a) / 8),
            f = new Uint8Array((s + 1 + e.interlace) * o);
          return (
            (r = e.tabs.CgBI ? t(r, f) : _inflate(r, f)),
            0 == e.interlace
              ? (r = _filterZero(r, e, 0, i, o))
              : 1 == e.interlace &&
                (r = (function _readInterlace(e, t) {
                  const r = t.width,
                    i = t.height,
                    o = _getBPP(t),
                    a = o >> 3,
                    s = Math.ceil((r * o) / 8),
                    f = new Uint8Array(i * s);
                  let l = 0;
                  const c = [0, 0, 4, 0, 2, 0, 1],
                    u = [0, 4, 0, 2, 0, 1, 0],
                    h = [8, 8, 8, 4, 4, 2, 2],
                    d = [8, 8, 4, 4, 2, 2, 1];
                  let A = 0;
                  for (; A < 7; ) {
                    const p = h[A],
                      m = d[A];
                    let w = 0,
                      v = 0,
                      b = c[A];
                    for (; b < i; ) ((b += p), v++);
                    let y = u[A];
                    for (; y < r; ) ((y += m), w++);
                    const E = Math.ceil((w * o) / 8);
                    _filterZero(e, t, l, w, v);
                    let F = 0,
                      _ = c[A];
                    for (; _ < i; ) {
                      let t = u[A],
                        i = (l + F * E) << 3;
                      for (; t < r; ) {
                        var g;
                        if (1 == o)
                          ((g = ((g = e[i >> 3]) >> (7 - (7 & i))) & 1),
                            (f[_ * s + (t >> 3)] |= g << (7 - ((7 & t) << 0))));
                        if (2 == o)
                          ((g = ((g = e[i >> 3]) >> (6 - (7 & i))) & 3),
                            (f[_ * s + (t >> 2)] |= g << (6 - ((3 & t) << 1))));
                        if (4 == o)
                          ((g = ((g = e[i >> 3]) >> (4 - (7 & i))) & 15),
                            (f[_ * s + (t >> 1)] |= g << (4 - ((1 & t) << 2))));
                        if (o >= 8) {
                          const r = _ * s + t * a;
                          for (let t = 0; t < a; t++) f[r + t] = e[(i >> 3) + t];
                        }
                        ((i += o), (t += m));
                      }
                      (F++, (_ += p));
                    }
                    (w * v != 0 && (l += v * (1 + E)), (A += 1));
                  }
                  return f;
                })(r, e)),
            r
          );
        }
        function _inflate(e, r) {
          return t(new Uint8Array(e.buffer, 2, e.length - 6), r);
        }
        var t = (function () {
          const e = { H: {} };
          return (
            (e.H.N = function (t, r) {
              const i = Uint8Array;
              let o,
                a,
                s = 0,
                f = 0,
                l = 0,
                c = 0,
                u = 0,
                h = 0,
                d = 0,
                A = 0,
                g = 0;
              if (3 == t[0] && 0 == t[1]) return r || new i(0);
              const p = e.H,
                m = p.b,
                w = p.e,
                v = p.R,
                b = p.n,
                y = p.A,
                E = p.Z,
                F = p.m,
                _ = null == r;
              for (_ && (r = new i((t.length >>> 2) << 5)); 0 == s; )
                if (((s = m(t, g, 1)), (f = m(t, g + 1, 2)), (g += 3), 0 != f)) {
                  if (
                    (_ && (r = e.H.W(r, A + (1 << 17))), 1 == f && ((o = F.J), (a = F.h), (h = 511), (d = 31)), 2 == f)
                  ) {
                    ((l = w(t, g, 5) + 257), (c = w(t, g + 5, 5) + 1), (u = w(t, g + 10, 4) + 4), (g += 14));
                    let e = 1;
                    for (var B = 0; B < 38; B += 2) ((F.Q[B] = 0), (F.Q[B + 1] = 0));
                    for (B = 0; B < u; B++) {
                      const r = w(t, g + 3 * B, 3);
                      ((F.Q[1 + (F.X[B] << 1)] = r), r > e && (e = r));
                    }
                    ((g += 3 * u),
                      b(F.Q, e),
                      y(F.Q, e, F.u),
                      (o = F.w),
                      (a = F.d),
                      (g = v(F.u, (1 << e) - 1, l + c, t, g, F.v)));
                    const r = p.V(F.v, 0, l, F.C);
                    h = (1 << r) - 1;
                    const i = p.V(F.v, l, c, F.D);
                    ((d = (1 << i) - 1), b(F.C, r), y(F.C, r, o), b(F.D, i), y(F.D, i, a));
                  }
                  for (;;) {
                    const e = o[E(t, g) & h];
                    g += 15 & e;
                    const i = e >>> 4;
                    if (i >>> 8 == 0) r[A++] = i;
                    else {
                      if (256 == i) break;
                      {
                        let e = A + i - 254;
                        if (i > 264) {
                          const r = F.q[i - 257];
                          ((e = A + (r >>> 3) + w(t, g, 7 & r)), (g += 7 & r));
                        }
                        const o = a[E(t, g) & d];
                        g += 15 & o;
                        const s = o >>> 4,
                          f = F.c[s],
                          l = (f >>> 4) + m(t, g, 15 & f);
                        for (g += 15 & f; A < e; )
                          ((r[A] = r[A++ - l]), (r[A] = r[A++ - l]), (r[A] = r[A++ - l]), (r[A] = r[A++ - l]));
                        A = e;
                      }
                    }
                  }
                } else {
                  0 != (7 & g) && (g += 8 - (7 & g));
                  const o = 4 + (g >>> 3),
                    a = t[o - 4] | (t[o - 3] << 8);
                  (_ && (r = e.H.W(r, A + a)),
                    r.set(new i(t.buffer, t.byteOffset + o, a), A),
                    (g = (o + a) << 3),
                    (A += a));
                }
              return r.length == A ? r : r.slice(0, A);
            }),
            (e.H.W = function (e, t) {
              const r = e.length;
              if (t <= r) return e;
              const i = new Uint8Array(r << 1);
              return (i.set(e, 0), i);
            }),
            (e.H.R = function (t, r, i, o, a, s) {
              const f = e.H.e,
                l = e.H.Z;
              let c = 0;
              for (; c < i; ) {
                const e = t[l(o, a) & r];
                a += 15 & e;
                const i = e >>> 4;
                if (i <= 15) ((s[c] = i), c++);
                else {
                  let e = 0,
                    t = 0;
                  16 == i
                    ? ((t = 3 + f(o, a, 2)), (a += 2), (e = s[c - 1]))
                    : 17 == i
                      ? ((t = 3 + f(o, a, 3)), (a += 3))
                      : 18 == i && ((t = 11 + f(o, a, 7)), (a += 7));
                  const r = c + t;
                  for (; c < r; ) ((s[c] = e), c++);
                }
              }
              return a;
            }),
            (e.H.V = function (e, t, r, i) {
              let o = 0,
                a = 0;
              const s = i.length >>> 1;
              for (; a < r; ) {
                const r = e[a + t];
                ((i[a << 1] = 0), (i[1 + (a << 1)] = r), r > o && (o = r), a++);
              }
              for (; a < s; ) ((i[a << 1] = 0), (i[1 + (a << 1)] = 0), a++);
              return o;
            }),
            (e.H.n = function (t, r) {
              const i = e.H.m,
                o = t.length;
              let a, s, f;
              let l;
              const c = i.j;
              for (var u = 0; u <= r; u++) c[u] = 0;
              for (u = 1; u < o; u += 2) c[t[u]]++;
              const h = i.K;
              for (a = 0, c[0] = 0, s = 1; s <= r; s++) ((a = (a + c[s - 1]) << 1), (h[s] = a));
              for (f = 0; f < o; f += 2) ((l = t[f + 1]), 0 != l && ((t[f] = h[l]), h[l]++));
            }),
            (e.H.A = function (t, r, i) {
              const o = t.length,
                a = e.H.m.r;
              for (let e = 0; e < o; e += 2)
                if (0 != t[e + 1]) {
                  const o = e >> 1,
                    s = t[e + 1],
                    f = (o << 4) | s,
                    l = r - s;
                  let c = t[e] << l;
                  const u = c + (1 << l);
                  for (; c != u; ) {
                    ((i[a[c] >>> (15 - r)] = f), c++);
                  }
                }
            }),
            (e.H.l = function (t, r) {
              const i = e.H.m.r,
                o = 15 - r;
              for (let e = 0; e < t.length; e += 2) {
                const a = t[e] << (r - t[e + 1]);
                t[e] = i[a] >>> o;
              }
            }),
            (e.H.M = function (e, t, r) {
              r <<= 7 & t;
              const i = t >>> 3;
              ((e[i] |= r), (e[i + 1] |= r >>> 8));
            }),
            (e.H.I = function (e, t, r) {
              r <<= 7 & t;
              const i = t >>> 3;
              ((e[i] |= r), (e[i + 1] |= r >>> 8), (e[i + 2] |= r >>> 16));
            }),
            (e.H.e = function (e, t, r) {
              return ((e[t >>> 3] | (e[1 + (t >>> 3)] << 8)) >>> (7 & t)) & ((1 << r) - 1);
            }),
            (e.H.b = function (e, t, r) {
              return ((e[t >>> 3] | (e[1 + (t >>> 3)] << 8) | (e[2 + (t >>> 3)] << 16)) >>> (7 & t)) & ((1 << r) - 1);
            }),
            (e.H.Z = function (e, t) {
              return (e[t >>> 3] | (e[1 + (t >>> 3)] << 8) | (e[2 + (t >>> 3)] << 16)) >>> (7 & t);
            }),
            (e.H.i = function (e, t) {
              return (
                (e[t >>> 3] | (e[1 + (t >>> 3)] << 8) | (e[2 + (t >>> 3)] << 16) | (e[3 + (t >>> 3)] << 24)) >>> (7 & t)
              );
            }),
            (e.H.m = (function () {
              const e = Uint16Array,
                t = Uint32Array;
              return {
                K: new e(16),
                j: new e(16),
                X: [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15],
                S: [
                  3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163,
                  195, 227, 258, 999, 999, 999,
                ],
                T: [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0, 0],
                q: new e(32),
                p: [
                  1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073,
                  4097, 6145, 8193, 12289, 16385, 24577, 65535, 65535,
                ],
                z: [
                  0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 0,
                  0,
                ],
                c: new t(32),
                J: new e(512),
                _: [],
                h: new e(32),
                $: [],
                w: new e(32768),
                C: [],
                v: [],
                d: new e(32768),
                D: [],
                u: new e(512),
                Q: [],
                r: new e(32768),
                s: new t(286),
                Y: new t(30),
                a: new t(19),
                t: new t(15e3),
                k: new e(65536),
                g: new e(32768),
              };
            })()),
            (function () {
              const t = e.H.m;
              for (var r = 0; r < 32768; r++) {
                let e = r;
                ((e = ((2863311530 & e) >>> 1) | ((1431655765 & e) << 1)),
                  (e = ((3435973836 & e) >>> 2) | ((858993459 & e) << 2)),
                  (e = ((4042322160 & e) >>> 4) | ((252645135 & e) << 4)),
                  (e = ((4278255360 & e) >>> 8) | ((16711935 & e) << 8)),
                  (t.r[r] = ((e >>> 16) | (e << 16)) >>> 17));
              }
              function n(e, t, r) {
                for (; 0 != t--; ) e.push(0, r);
              }
              for (r = 0; r < 32; r++) ((t.q[r] = (t.S[r] << 3) | t.T[r]), (t.c[r] = (t.p[r] << 4) | t.z[r]));
              (n(t._, 144, 8),
                n(t._, 112, 9),
                n(t._, 24, 7),
                n(t._, 8, 8),
                e.H.n(t._, 9),
                e.H.A(t._, 9, t.J),
                e.H.l(t._, 9),
                n(t.$, 32, 5),
                e.H.n(t.$, 5),
                e.H.A(t.$, 5, t.h),
                e.H.l(t.$, 5),
                n(t.Q, 19, 0),
                n(t.C, 286, 0),
                n(t.D, 30, 0),
                n(t.v, 320, 0));
            })(),
            e.H.N
          );
        })();
        function _getBPP(e) {
          return [1, null, 3, 1, 2, null, 4][e.ctype] * e.depth;
        }
        function _filterZero(e, t, r, i, o) {
          let a = _getBPP(t);
          const s = Math.ceil((i * a) / 8);
          let f, l;
          a = Math.ceil(a / 8);
          let c = e[r],
            u = 0;
          if ((c > 1 && (e[r] = [0, 0, 1][c - 2]), 3 == c))
            for (u = a; u < s; u++) e[u + 1] = (e[u + 1] + (e[u + 1 - a] >>> 1)) & 255;
          for (let t = 0; t < o; t++)
            if (((f = r + t * s), (l = f + t + 1), (c = e[l - 1]), (u = 0), 0 == c))
              for (; u < s; u++) e[f + u] = e[l + u];
            else if (1 == c) {
              for (; u < a; u++) e[f + u] = e[l + u];
              for (; u < s; u++) e[f + u] = e[l + u] + e[f + u - a];
            } else if (2 == c) for (; u < s; u++) e[f + u] = e[l + u] + e[f + u - s];
            else if (3 == c) {
              for (; u < a; u++) e[f + u] = e[l + u] + (e[f + u - s] >>> 1);
              for (; u < s; u++) e[f + u] = e[l + u] + ((e[f + u - s] + e[f + u - a]) >>> 1);
            } else {
              for (; u < a; u++) e[f + u] = e[l + u] + _paeth(0, e[f + u - s], 0);
              for (; u < s; u++) e[f + u] = e[l + u] + _paeth(e[f + u - a], e[f + u - s], e[f + u - a - s]);
            }
          return e;
        }
        function _paeth(e, t, r) {
          const i = e + t - r,
            o = i - e,
            a = i - t,
            s = i - r;
          return o * o <= a * a && o * o <= s * s ? e : a * a <= s * s ? t : r;
        }
        function _IHDR(t, r, i) {
          ((i.width = e.readUint(t, r)),
            (r += 4),
            (i.height = e.readUint(t, r)),
            (r += 4),
            (i.depth = t[r]),
            r++,
            (i.ctype = t[r]),
            r++,
            (i.compress = t[r]),
            r++,
            (i.filter = t[r]),
            r++,
            (i.interlace = t[r]),
            r++);
        }
        function _copyTile(e, t, r, i, o, a, s, f, l) {
          const c = Math.min(t, o),
            u = Math.min(r, a);
          let h = 0,
            d = 0;
          for (let r = 0; r < u; r++)
            for (let a = 0; a < c; a++)
              if (
                (s >= 0 && f >= 0
                  ? ((h = (r * t + a) << 2), (d = ((f + r) * o + s + a) << 2))
                  : ((h = ((-f + r) * t - s + a) << 2), (d = (r * o + a) << 2)),
                0 == l)
              )
                ((i[d] = e[h]), (i[d + 1] = e[h + 1]), (i[d + 2] = e[h + 2]), (i[d + 3] = e[h + 3]));
              else if (1 == l) {
                var A = e[h + 3] * (1 / 255),
                  g = e[h] * A,
                  p = e[h + 1] * A,
                  m = e[h + 2] * A,
                  w = i[d + 3] * (1 / 255),
                  v = i[d] * w,
                  b = i[d + 1] * w,
                  y = i[d + 2] * w;
                const t = 1 - A,
                  r = A + w * t,
                  o = 0 == r ? 0 : 1 / r;
                ((i[d + 3] = 255 * r),
                  (i[d + 0] = (g + v * t) * o),
                  (i[d + 1] = (p + b * t) * o),
                  (i[d + 2] = (m + y * t) * o));
              } else if (2 == l) {
                ((A = e[h + 3]),
                  (g = e[h]),
                  (p = e[h + 1]),
                  (m = e[h + 2]),
                  (w = i[d + 3]),
                  (v = i[d]),
                  (b = i[d + 1]),
                  (y = i[d + 2]));
                A == w && g == v && p == b && m == y
                  ? ((i[d] = 0), (i[d + 1] = 0), (i[d + 2] = 0), (i[d + 3] = 0))
                  : ((i[d] = g), (i[d + 1] = p), (i[d + 2] = m), (i[d + 3] = A));
              } else if (3 == l) {
                ((A = e[h + 3]),
                  (g = e[h]),
                  (p = e[h + 1]),
                  (m = e[h + 2]),
                  (w = i[d + 3]),
                  (v = i[d]),
                  (b = i[d + 1]),
                  (y = i[d + 2]));
                if (A == w && g == v && p == b && m == y) continue;
                if (A < 220 && w > 20) return !1;
              }
          return !0;
        }
        return {
          decode: function decode(r) {
            const i = new Uint8Array(r);
            let o = 8;
            const a = e,
              s = a.readUshort,
              f = a.readUint,
              l = { tabs: {}, frames: [] },
              c = new Uint8Array(i.length);
            let u,
              h = 0,
              d = 0;
            const A = [137, 80, 78, 71, 13, 10, 26, 10];
            for (var g = 0; g < 8; g++) if (i[g] != A[g]) throw 'The input is not a PNG file!';
            for (; o < i.length; ) {
              const e = a.readUint(i, o);
              o += 4;
              const r = a.readASCII(i, o, 4);
              if (((o += 4), 'IHDR' == r)) _IHDR(i, o, l);
              else if ('iCCP' == r) {
                for (var p = o; 0 != i[p]; ) p++;
                (a.readASCII(i, o, p - o), i[p + 1]);
                const s = i.slice(p + 2, o + e);
                let f = null;
                try {
                  f = _inflate(s);
                } catch (e) {
                  f = t(s);
                }
                l.tabs[r] = f;
              } else if ('CgBI' == r) l.tabs[r] = i.slice(o, o + 4);
              else if ('IDAT' == r) {
                for (g = 0; g < e; g++) c[h + g] = i[o + g];
                h += e;
              } else if ('acTL' == r)
                ((l.tabs[r] = { num_frames: f(i, o), num_plays: f(i, o + 4) }), (u = new Uint8Array(i.length)));
              else if ('fcTL' == r) {
                if (0 != d)
                  (((E = l.frames[l.frames.length - 1]).data = _decompress(
                    l,
                    u.slice(0, d),
                    E.rect.width,
                    E.rect.height,
                  )),
                    (d = 0));
                const e = { x: f(i, o + 12), y: f(i, o + 16), width: f(i, o + 4), height: f(i, o + 8) };
                let t = s(i, o + 22);
                t = s(i, o + 20) / (0 == t ? 100 : t);
                const r = { rect: e, delay: Math.round(1e3 * t), dispose: i[o + 24], blend: i[o + 25] };
                l.frames.push(r);
              } else if ('fdAT' == r) {
                for (g = 0; g < e - 4; g++) u[d + g] = i[o + g + 4];
                d += e - 4;
              } else if ('pHYs' == r) l.tabs[r] = [a.readUint(i, o), a.readUint(i, o + 4), i[o + 8]];
              else if ('cHRM' == r) {
                l.tabs[r] = [];
                for (g = 0; g < 8; g++) l.tabs[r].push(a.readUint(i, o + 4 * g));
              } else if ('tEXt' == r || 'zTXt' == r) {
                null == l.tabs[r] && (l.tabs[r] = {});
                var m = a.nextZero(i, o),
                  w = a.readASCII(i, o, m - o),
                  v = o + e - m - 1;
                if ('tEXt' == r) y = a.readASCII(i, m + 1, v);
                else {
                  var b = _inflate(i.slice(m + 2, m + 2 + v));
                  y = a.readUTF8(b, 0, b.length);
                }
                l.tabs[r][w] = y;
              } else if ('iTXt' == r) {
                null == l.tabs[r] && (l.tabs[r] = {});
                ((m = 0), (p = o));
                m = a.nextZero(i, p);
                w = a.readASCII(i, p, m - p);
                const t = i[(p = m + 1)];
                var y;
                (i[p + 1],
                  (p += 2),
                  (m = a.nextZero(i, p)),
                  a.readASCII(i, p, m - p),
                  (p = m + 1),
                  (m = a.nextZero(i, p)),
                  a.readUTF8(i, p, m - p));
                v = e - ((p = m + 1) - o);
                if (0 == t) y = a.readUTF8(i, p, v);
                else {
                  b = _inflate(i.slice(p, p + v));
                  y = a.readUTF8(b, 0, b.length);
                }
                l.tabs[r][w] = y;
              } else if ('PLTE' == r) l.tabs[r] = a.readBytes(i, o, e);
              else if ('hIST' == r) {
                const e = l.tabs.PLTE.length / 3;
                l.tabs[r] = [];
                for (g = 0; g < e; g++) l.tabs[r].push(s(i, o + 2 * g));
              } else if ('tRNS' == r)
                3 == l.ctype
                  ? (l.tabs[r] = a.readBytes(i, o, e))
                  : 0 == l.ctype
                    ? (l.tabs[r] = s(i, o))
                    : 2 == l.ctype && (l.tabs[r] = [s(i, o), s(i, o + 2), s(i, o + 4)]);
              else if ('gAMA' == r) l.tabs[r] = a.readUint(i, o) / 1e5;
              else if ('sRGB' == r) l.tabs[r] = i[o];
              else if ('bKGD' == r)
                0 == l.ctype || 4 == l.ctype
                  ? (l.tabs[r] = [s(i, o)])
                  : 2 == l.ctype || 6 == l.ctype
                    ? (l.tabs[r] = [s(i, o), s(i, o + 2), s(i, o + 4)])
                    : 3 == l.ctype && (l.tabs[r] = i[o]);
              else if ('IEND' == r) break;
              ((o += e), a.readUint(i, o), (o += 4));
            }
            var E;
            return (
              0 != d &&
                ((E = l.frames[l.frames.length - 1]).data = _decompress(l, u.slice(0, d), E.rect.width, E.rect.height)),
              (l.data = _decompress(l, c, l.width, l.height)),
              delete l.compress,
              delete l.interlace,
              delete l.filter,
              l
            );
          },
          toRGBA8: function toRGBA8(e) {
            const t = e.width,
              r = e.height;
            if (null == e.tabs.acTL) return [decodeImage(e.data, t, r, e).buffer];
            const i = [];
            null == e.frames[0].data && (e.frames[0].data = e.data);
            const o = t * r * 4,
              a = new Uint8Array(o),
              s = new Uint8Array(o),
              f = new Uint8Array(o);
            for (let c = 0; c < e.frames.length; c++) {
              const u = e.frames[c],
                h = u.rect.x,
                d = u.rect.y,
                A = u.rect.width,
                g = u.rect.height,
                p = decodeImage(u.data, A, g, e);
              if (0 != c) for (var l = 0; l < o; l++) f[l] = a[l];
              if (
                (0 == u.blend
                  ? _copyTile(p, A, g, a, t, r, h, d, 0)
                  : 1 == u.blend && _copyTile(p, A, g, a, t, r, h, d, 1),
                i.push(a.buffer.slice(0)),
                0 == u.dispose)
              );
              else if (1 == u.dispose) _copyTile(s, A, g, a, t, r, h, d, 0);
              else if (2 == u.dispose) for (l = 0; l < o; l++) a[l] = f[l];
            }
            return i;
          },
          _paeth: _paeth,
          _copyTile: _copyTile,
          _bin: e,
        };
      })();
      !(function () {
        const { _copyTile: e } = UPNG,
          { _bin: t } = UPNG,
          r = UPNG._paeth;
        var i = {
          table: (function () {
            const e = new Uint32Array(256);
            for (let t = 0; t < 256; t++) {
              let r = t;
              for (let e = 0; e < 8; e++) 1 & r ? (r = 3988292384 ^ (r >>> 1)) : (r >>>= 1);
              e[t] = r;
            }
            return e;
          })(),
          update(e, t, r, o) {
            for (let a = 0; a < o; a++) e = i.table[255 & (e ^ t[r + a])] ^ (e >>> 8);
            return e;
          },
          crc: (e, t, r) => 4294967295 ^ i.update(4294967295, e, t, r),
        };
        function addErr(e, t, r, i) {
          ((t[r] += (e[0] * i) >> 4),
            (t[r + 1] += (e[1] * i) >> 4),
            (t[r + 2] += (e[2] * i) >> 4),
            (t[r + 3] += (e[3] * i) >> 4));
        }
        function N(e) {
          return Math.max(0, Math.min(255, e));
        }
        function D(e, t) {
          const r = e[0] - t[0],
            i = e[1] - t[1],
            o = e[2] - t[2],
            a = e[3] - t[3];
          return r * r + i * i + o * o + a * a;
        }
        function dither(e, t, r, i, o, a, s) {
          null == s && (s = 1);
          const f = i.length,
            l = [];
          for (var c = 0; c < f; c++) {
            const e = i[c];
            l.push([(e >>> 0) & 255, (e >>> 8) & 255, (e >>> 16) & 255, (e >>> 24) & 255]);
          }
          for (c = 0; c < f; c++) {
            let e = 4294967295;
            for (var u = 0, h = 0; h < f; h++) {
              var d = D(l[c], l[h]);
              h != c && d < e && ((e = d), (u = h));
            }
          }
          const A = new Uint32Array(o.buffer),
            g = new Int16Array(t * r * 4),
            p = [0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5];
          for (c = 0; c < p.length; c++) p[c] = 255 * ((p[c] + 0.5) / 16 - 0.5);
          for (let o = 0; o < r; o++)
            for (let w = 0; w < t; w++) {
              var m;
              c = 4 * (o * t + w);
              if (2 != s) m = [N(e[c] + g[c]), N(e[c + 1] + g[c + 1]), N(e[c + 2] + g[c + 2]), N(e[c + 3] + g[c + 3])];
              else {
                d = p[4 * (3 & o) + (3 & w)];
                m = [N(e[c] + d), N(e[c + 1] + d), N(e[c + 2] + d), N(e[c + 3] + d)];
              }
              u = 0;
              let v = 16777215;
              for (h = 0; h < f; h++) {
                const e = D(m, l[h]);
                e < v && ((v = e), (u = h));
              }
              const b = l[u],
                y = [m[0] - b[0], m[1] - b[1], m[2] - b[2], m[3] - b[3]];
              (1 == s &&
                (w != t - 1 && addErr(y, g, c + 4, 7),
                o != r - 1 &&
                  (0 != w && addErr(y, g, c + 4 * t - 4, 3),
                  addErr(y, g, c + 4 * t, 5),
                  w != t - 1 && addErr(y, g, c + 4 * t + 4, 1))),
                (a[c >> 2] = u),
                (A[c >> 2] = i[u]));
            }
        }
        function _main(e, r, o, a, s) {
          null == s && (s = {});
          const { crc: f } = i,
            l = t.writeUint,
            c = t.writeUshort,
            u = t.writeASCII;
          let h = 8;
          const d = e.frames.length > 1;
          let A,
            g = !1,
            p = 33 + (d ? 20 : 0);
          if (
            (null != s.sRGB && (p += 13),
            null != s.pHYs && (p += 21),
            null != s.iCCP && ((A = pako.deflate(s.iCCP)), (p += 21 + A.length + 4)),
            3 == e.ctype)
          ) {
            for (var m = e.plte.length, w = 0; w < m; w++) e.plte[w] >>> 24 != 255 && (g = !0);
            p += 8 + 3 * m + 4 + (g ? 8 + 1 * m + 4 : 0);
          }
          for (var v = 0; v < e.frames.length; v++) {
            (d && (p += 38), (p += (F = e.frames[v]).cimg.length + 12), 0 != v && (p += 4));
          }
          p += 12;
          const b = new Uint8Array(p),
            y = [137, 80, 78, 71, 13, 10, 26, 10];
          for (w = 0; w < 8; w++) b[w] = y[w];
          if (
            (l(b, h, 13),
            (h += 4),
            u(b, h, 'IHDR'),
            (h += 4),
            l(b, h, r),
            (h += 4),
            l(b, h, o),
            (h += 4),
            (b[h] = e.depth),
            h++,
            (b[h] = e.ctype),
            h++,
            (b[h] = 0),
            h++,
            (b[h] = 0),
            h++,
            (b[h] = 0),
            h++,
            l(b, h, f(b, h - 17, 17)),
            (h += 4),
            null != s.sRGB &&
              (l(b, h, 1),
              (h += 4),
              u(b, h, 'sRGB'),
              (h += 4),
              (b[h] = s.sRGB),
              h++,
              l(b, h, f(b, h - 5, 5)),
              (h += 4)),
            null != s.iCCP)
          ) {
            const e = 13 + A.length;
            (l(b, h, e),
              (h += 4),
              u(b, h, 'iCCP'),
              (h += 4),
              u(b, h, 'ICC profile'),
              (h += 11),
              (h += 2),
              b.set(A, h),
              (h += A.length),
              l(b, h, f(b, h - (e + 4), e + 4)),
              (h += 4));
          }
          if (
            (null != s.pHYs &&
              (l(b, h, 9),
              (h += 4),
              u(b, h, 'pHYs'),
              (h += 4),
              l(b, h, s.pHYs[0]),
              (h += 4),
              l(b, h, s.pHYs[1]),
              (h += 4),
              (b[h] = s.pHYs[2]),
              h++,
              l(b, h, f(b, h - 13, 13)),
              (h += 4)),
            d &&
              (l(b, h, 8),
              (h += 4),
              u(b, h, 'acTL'),
              (h += 4),
              l(b, h, e.frames.length),
              (h += 4),
              l(b, h, null != s.loop ? s.loop : 0),
              (h += 4),
              l(b, h, f(b, h - 12, 12)),
              (h += 4)),
            3 == e.ctype)
          ) {
            (l(b, h, 3 * (m = e.plte.length)), (h += 4), u(b, h, 'PLTE'), (h += 4));
            for (w = 0; w < m; w++) {
              const t = 3 * w,
                r = e.plte[w],
                i = 255 & r,
                o = (r >>> 8) & 255,
                a = (r >>> 16) & 255;
              ((b[h + t + 0] = i), (b[h + t + 1] = o), (b[h + t + 2] = a));
            }
            if (((h += 3 * m), l(b, h, f(b, h - 3 * m - 4, 3 * m + 4)), (h += 4), g)) {
              (l(b, h, m), (h += 4), u(b, h, 'tRNS'), (h += 4));
              for (w = 0; w < m; w++) b[h + w] = (e.plte[w] >>> 24) & 255;
              ((h += m), l(b, h, f(b, h - m - 4, m + 4)), (h += 4));
            }
          }
          let E = 0;
          for (v = 0; v < e.frames.length; v++) {
            var F = e.frames[v];
            d &&
              (l(b, h, 26),
              (h += 4),
              u(b, h, 'fcTL'),
              (h += 4),
              l(b, h, E++),
              (h += 4),
              l(b, h, F.rect.width),
              (h += 4),
              l(b, h, F.rect.height),
              (h += 4),
              l(b, h, F.rect.x),
              (h += 4),
              l(b, h, F.rect.y),
              (h += 4),
              c(b, h, a[v]),
              (h += 2),
              c(b, h, 1e3),
              (h += 2),
              (b[h] = F.dispose),
              h++,
              (b[h] = F.blend),
              h++,
              l(b, h, f(b, h - 30, 30)),
              (h += 4));
            const t = F.cimg;
            (l(b, h, (m = t.length) + (0 == v ? 0 : 4)), (h += 4));
            const r = h;
            (u(b, h, 0 == v ? 'IDAT' : 'fdAT'),
              (h += 4),
              0 != v && (l(b, h, E++), (h += 4)),
              b.set(t, h),
              (h += m),
              l(b, h, f(b, r, h - r)),
              (h += 4));
          }
          return (l(b, h, 0), (h += 4), u(b, h, 'IEND'), (h += 4), l(b, h, f(b, h - 4, 4)), (h += 4), b.buffer);
        }
        function compressPNG(e, t, r) {
          for (let i = 0; i < e.frames.length; i++) {
            const o = e.frames[i];
            o.rect.width;
            const a = o.rect.height,
              s = new Uint8Array(a * o.bpl + a);
            o.cimg = _filterZero(o.img, a, o.bpp, o.bpl, s, t, r);
          }
        }
        function compress(t, r, i, o, a) {
          const s = a[0],
            f = a[1],
            l = a[2],
            c = a[3],
            u = a[4],
            h = a[5];
          let d = 6,
            A = 8,
            g = 255;
          for (var p = 0; p < t.length; p++) {
            const e = new Uint8Array(t[p]);
            for (var m = e.length, w = 0; w < m; w += 4) g &= e[w + 3];
          }
          const v = 255 != g,
            b = (function framize(t, r, i, o, a, s) {
              const f = [];
              for (var l = 0; l < t.length; l++) {
                const h = new Uint8Array(t[l]),
                  A = new Uint32Array(h.buffer);
                var c;
                let g = 0,
                  p = 0,
                  m = r,
                  w = i,
                  v = o ? 1 : 0;
                if (0 != l) {
                  const b = s || o || 1 == l || 0 != f[l - 2].dispose ? 1 : 2;
                  let y = 0,
                    E = 1e9;
                  for (let e = 0; e < b; e++) {
                    var u = new Uint8Array(t[l - 1 - e]);
                    const o = new Uint32Array(t[l - 1 - e]);
                    let s = r,
                      f = i,
                      c = -1,
                      h = -1;
                    for (let e = 0; e < i; e++)
                      for (let t = 0; t < r; t++) {
                        A[(d = e * r + t)] != o[d] &&
                          (t < s && (s = t), t > c && (c = t), e < f && (f = e), e > h && (h = e));
                      }
                    (-1 == c && (s = f = c = h = 0), a && (1 == (1 & s) && s--, 1 == (1 & f) && f--));
                    const v = (c - s + 1) * (h - f + 1);
                    v < E && ((E = v), (y = e), (g = s), (p = f), (m = c - s + 1), (w = h - f + 1));
                  }
                  u = new Uint8Array(t[l - 1 - y]);
                  (1 == y && (f[l - 1].dispose = 2),
                    (c = new Uint8Array(m * w * 4)),
                    e(u, r, i, c, m, w, -g, -p, 0),
                    (v = e(h, r, i, c, m, w, -g, -p, 3) ? 1 : 0),
                    1 == v
                      ? _prepareDiff(h, r, i, c, { x: g, y: p, width: m, height: w })
                      : e(h, r, i, c, m, w, -g, -p, 0));
                } else c = h.slice(0);
                f.push({ rect: { x: g, y: p, width: m, height: w }, img: c, blend: v, dispose: 0 });
              }
              if (o)
                for (l = 0; l < f.length; l++) {
                  if (1 == (A = f[l]).blend) continue;
                  const e = A.rect,
                    o = f[l - 1].rect,
                    s = Math.min(e.x, o.x),
                    c = Math.min(e.y, o.y),
                    u = {
                      x: s,
                      y: c,
                      width: Math.max(e.x + e.width, o.x + o.width) - s,
                      height: Math.max(e.y + e.height, o.y + o.height) - c,
                    };
                  ((f[l - 1].dispose = 1),
                    l - 1 != 0 && _updateFrame(t, r, i, f, l - 1, u, a),
                    _updateFrame(t, r, i, f, l, u, a));
                }
              let h = 0;
              if (1 != t.length)
                for (var d = 0; d < f.length; d++) {
                  var A;
                  h += (A = f[d]).rect.width * A.rect.height;
                }
              return f;
            })(t, r, i, s, f, l),
            y = {},
            E = [],
            F = [];
          if (0 != o) {
            const e = [];
            for (w = 0; w < b.length; w++) e.push(b[w].img.buffer);
            const t = (function concatRGBA(e) {
                let t = 0;
                for (var r = 0; r < e.length; r++) t += e[r].byteLength;
                const i = new Uint8Array(t);
                let o = 0;
                for (r = 0; r < e.length; r++) {
                  const t = new Uint8Array(e[r]),
                    a = t.length;
                  for (let e = 0; e < a; e += 4) {
                    let r = t[e],
                      a = t[e + 1],
                      s = t[e + 2];
                    const f = t[e + 3];
                    (0 == f && (r = a = s = 0),
                      (i[o + e] = r),
                      (i[o + e + 1] = a),
                      (i[o + e + 2] = s),
                      (i[o + e + 3] = f));
                  }
                  o += a;
                }
                return i.buffer;
              })(e),
              r = quantize(t, o);
            for (w = 0; w < r.plte.length; w++) E.push(r.plte[w].est.rgba);
            let i = 0;
            for (w = 0; w < b.length; w++) {
              const e = (B = b[w]).img.length;
              var _ = new Uint8Array(r.inds.buffer, i >> 2, e >> 2);
              F.push(_);
              const t = new Uint8Array(r.abuf, i, e);
              (h && dither(B.img, B.rect.width, B.rect.height, E, t, _), B.img.set(t), (i += e));
            }
          } else
            for (p = 0; p < b.length; p++) {
              var B = b[p];
              const e = new Uint32Array(B.img.buffer);
              var U = B.rect.width;
              ((m = e.length), (_ = new Uint8Array(m)));
              F.push(_);
              for (w = 0; w < m; w++) {
                const t = e[w];
                if (0 != w && t == e[w - 1]) _[w] = _[w - 1];
                else if (w > U && t == e[w - U]) _[w] = _[w - U];
                else {
                  let e = y[t];
                  if (null == e && ((y[t] = e = E.length), E.push(t), E.length >= 300)) break;
                  _[w] = e;
                }
              }
            }
          const C = E.length;
          C <= 256 && 0 == u && ((A = C <= 2 ? 1 : C <= 4 ? 2 : C <= 16 ? 4 : 8), (A = Math.max(A, c)));
          for (p = 0; p < b.length; p++) {
            ((B = b[p]).rect.x, B.rect.y);
            U = B.rect.width;
            const e = B.rect.height;
            let t = B.img;
            new Uint32Array(t.buffer);
            let r = 4 * U,
              i = 4;
            if (C <= 256 && 0 == u) {
              r = Math.ceil((A * U) / 8);
              var I = new Uint8Array(r * e);
              const o = F[p];
              for (let t = 0; t < e; t++) {
                w = t * r;
                const e = t * U;
                if (8 == A) for (var Q = 0; Q < U; Q++) I[w + Q] = o[e + Q];
                else if (4 == A) for (Q = 0; Q < U; Q++) I[w + (Q >> 1)] |= o[e + Q] << (4 - 4 * (1 & Q));
                else if (2 == A) for (Q = 0; Q < U; Q++) I[w + (Q >> 2)] |= o[e + Q] << (6 - 2 * (3 & Q));
                else if (1 == A) for (Q = 0; Q < U; Q++) I[w + (Q >> 3)] |= o[e + Q] << (7 - 1 * (7 & Q));
              }
              ((t = I), (d = 3), (i = 1));
            } else if (0 == v && 1 == b.length) {
              I = new Uint8Array(U * e * 3);
              const o = U * e;
              for (w = 0; w < o; w++) {
                const e = 3 * w,
                  r = 4 * w;
                ((I[e] = t[r]), (I[e + 1] = t[r + 1]), (I[e + 2] = t[r + 2]));
              }
              ((t = I), (d = 2), (i = 3), (r = 3 * U));
            }
            ((B.img = t), (B.bpl = r), (B.bpp = i));
          }
          return { ctype: d, depth: A, plte: E, frames: b };
        }
        function _updateFrame(t, r, i, o, a, s, f) {
          const l = Uint8Array,
            c = Uint32Array,
            u = new l(t[a - 1]),
            h = new c(t[a - 1]),
            d = a + 1 < t.length ? new l(t[a + 1]) : null,
            A = new l(t[a]),
            g = new c(A.buffer);
          let p = r,
            m = i,
            w = -1,
            v = -1;
          for (let e = 0; e < s.height; e++)
            for (let t = 0; t < s.width; t++) {
              const i = s.x + t,
                f = s.y + e,
                l = f * r + i,
                c = g[l];
              0 == c ||
                (0 == o[a - 1].dispose && h[l] == c && (null == d || 0 != d[4 * l + 3])) ||
                (i < p && (p = i), i > w && (w = i), f < m && (m = f), f > v && (v = f));
            }
          (-1 == w && (p = m = w = v = 0),
            f && (1 == (1 & p) && p--, 1 == (1 & m) && m--),
            (s = { x: p, y: m, width: w - p + 1, height: v - m + 1 }));
          const b = o[a];
          ((b.rect = s),
            (b.blend = 1),
            (b.img = new Uint8Array(s.width * s.height * 4)),
            0 == o[a - 1].dispose
              ? (e(u, r, i, b.img, s.width, s.height, -s.x, -s.y, 0), _prepareDiff(A, r, i, b.img, s))
              : e(A, r, i, b.img, s.width, s.height, -s.x, -s.y, 0));
        }
        function _prepareDiff(t, r, i, o, a) {
          e(t, r, i, o, a.width, a.height, -a.x, -a.y, 2);
        }
        function _filterZero(e, t, r, i, o, a, s) {
          const f = [];
          let l,
            c = [0, 1, 2, 3, 4];
          (-1 != a ? (c = [a]) : (t * i > 5e5 || 1 == r) && (c = [0]), s && (l = { level: 0 }));
          const u = UZIP;
          for (var h = 0; h < c.length; h++) {
            for (let a = 0; a < t; a++) _filterLine(o, e, a, i, r, c[h]);
            f.push(u.deflate(o, l));
          }
          let d,
            A = 1e9;
          for (h = 0; h < f.length; h++) f[h].length < A && ((d = h), (A = f[h].length));
          return f[d];
        }
        function _filterLine(e, t, i, o, a, s) {
          const f = i * o;
          let l = f + i;
          if (((e[l] = s), l++, 0 == s))
            if (o < 500) for (var c = 0; c < o; c++) e[l + c] = t[f + c];
            else e.set(new Uint8Array(t.buffer, f, o), l);
          else if (1 == s) {
            for (c = 0; c < a; c++) e[l + c] = t[f + c];
            for (c = a; c < o; c++) e[l + c] = (t[f + c] - t[f + c - a] + 256) & 255;
          } else if (0 == i) {
            for (c = 0; c < a; c++) e[l + c] = t[f + c];
            if (2 == s) for (c = a; c < o; c++) e[l + c] = t[f + c];
            if (3 == s) for (c = a; c < o; c++) e[l + c] = (t[f + c] - (t[f + c - a] >> 1) + 256) & 255;
            if (4 == s) for (c = a; c < o; c++) e[l + c] = (t[f + c] - r(t[f + c - a], 0, 0) + 256) & 255;
          } else {
            if (2 == s) for (c = 0; c < o; c++) e[l + c] = (t[f + c] + 256 - t[f + c - o]) & 255;
            if (3 == s) {
              for (c = 0; c < a; c++) e[l + c] = (t[f + c] + 256 - (t[f + c - o] >> 1)) & 255;
              for (c = a; c < o; c++) e[l + c] = (t[f + c] + 256 - ((t[f + c - o] + t[f + c - a]) >> 1)) & 255;
            }
            if (4 == s) {
              for (c = 0; c < a; c++) e[l + c] = (t[f + c] + 256 - r(0, t[f + c - o], 0)) & 255;
              for (c = a; c < o; c++)
                e[l + c] = (t[f + c] + 256 - r(t[f + c - a], t[f + c - o], t[f + c - a - o])) & 255;
            }
          }
        }
        function quantize(e, t) {
          const r = new Uint8Array(e),
            i = r.slice(0),
            o = new Uint32Array(i.buffer),
            a = getKDtree(i, t),
            s = a[0],
            f = a[1],
            l = r.length,
            c = new Uint8Array(l >> 2);
          let u;
          if (r.length < 2e7)
            for (var h = 0; h < l; h += 4) {
              ((u = getNearest(
                s,
                (d = r[h] * (1 / 255)),
                (A = r[h + 1] * (1 / 255)),
                (g = r[h + 2] * (1 / 255)),
                (p = r[h + 3] * (1 / 255)),
              )),
                (c[h >> 2] = u.ind),
                (o[h >> 2] = u.est.rgba));
            }
          else
            for (h = 0; h < l; h += 4) {
              var d = r[h] * (1 / 255),
                A = r[h + 1] * (1 / 255),
                g = r[h + 2] * (1 / 255),
                p = r[h + 3] * (1 / 255);
              for (u = s; u.left; ) u = planeDst(u.est, d, A, g, p) <= 0 ? u.left : u.right;
              ((c[h >> 2] = u.ind), (o[h >> 2] = u.est.rgba));
            }
          return { abuf: i.buffer, inds: c, plte: f };
        }
        function getKDtree(e, t, r) {
          null == r && (r = 1e-4);
          const i = new Uint32Array(e.buffer),
            o = { i0: 0, i1: e.length, bst: null, est: null, tdst: 0, left: null, right: null };
          ((o.bst = stats(e, o.i0, o.i1)), (o.est = estats(o.bst)));
          const a = [o];
          for (; a.length < t; ) {
            let t = 0,
              o = 0;
            for (var s = 0; s < a.length; s++) a[s].est.L > t && ((t = a[s].est.L), (o = s));
            if (t < r) break;
            const f = a[o],
              l = splitPixels(e, i, f.i0, f.i1, f.est.e, f.est.eMq255);
            if (f.i0 >= l || f.i1 <= l) {
              f.est.L = 0;
              continue;
            }
            const c = { i0: f.i0, i1: l, bst: null, est: null, tdst: 0, left: null, right: null };
            ((c.bst = stats(e, c.i0, c.i1)), (c.est = estats(c.bst)));
            const u = { i0: l, i1: f.i1, bst: null, est: null, tdst: 0, left: null, right: null };
            u.bst = { R: [], m: [], N: f.bst.N - c.bst.N };
            for (s = 0; s < 16; s++) u.bst.R[s] = f.bst.R[s] - c.bst.R[s];
            for (s = 0; s < 4; s++) u.bst.m[s] = f.bst.m[s] - c.bst.m[s];
            ((u.est = estats(u.bst)), (f.left = c), (f.right = u), (a[o] = c), a.push(u));
          }
          a.sort((e, t) => t.bst.N - e.bst.N);
          for (s = 0; s < a.length; s++) a[s].ind = s;
          return [o, a];
        }
        function getNearest(e, t, r, i, o) {
          if (null == e.left)
            return (
              (e.tdst = (function dist(e, t, r, i, o) {
                const a = t - e[0],
                  s = r - e[1],
                  f = i - e[2],
                  l = o - e[3];
                return a * a + s * s + f * f + l * l;
              })(e.est.q, t, r, i, o)),
              e
            );
          const a = planeDst(e.est, t, r, i, o);
          let s = e.left,
            f = e.right;
          a > 0 && ((s = e.right), (f = e.left));
          const l = getNearest(s, t, r, i, o);
          if (l.tdst <= a * a) return l;
          const c = getNearest(f, t, r, i, o);
          return c.tdst < l.tdst ? c : l;
        }
        function planeDst(e, t, r, i, o) {
          const { e: a } = e;
          return a[0] * t + a[1] * r + a[2] * i + a[3] * o - e.eMq;
        }
        function splitPixels(e, t, r, i, o, a) {
          for (i -= 4; r < i; ) {
            for (; vecDot(e, r, o) <= a; ) r += 4;
            for (; vecDot(e, i, o) > a; ) i -= 4;
            if (r >= i) break;
            const s = t[r >> 2];
            ((t[r >> 2] = t[i >> 2]), (t[i >> 2] = s), (r += 4), (i -= 4));
          }
          for (; vecDot(e, r, o) > a; ) r -= 4;
          return r + 4;
        }
        function vecDot(e, t, r) {
          return e[t] * r[0] + e[t + 1] * r[1] + e[t + 2] * r[2] + e[t + 3] * r[3];
        }
        function stats(e, t, r) {
          const i = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            o = [0, 0, 0, 0],
            a = (r - t) >> 2;
          for (let a = t; a < r; a += 4) {
            const t = e[a] * (1 / 255),
              r = e[a + 1] * (1 / 255),
              s = e[a + 2] * (1 / 255),
              f = e[a + 3] * (1 / 255);
            ((o[0] += t),
              (o[1] += r),
              (o[2] += s),
              (o[3] += f),
              (i[0] += t * t),
              (i[1] += t * r),
              (i[2] += t * s),
              (i[3] += t * f),
              (i[5] += r * r),
              (i[6] += r * s),
              (i[7] += r * f),
              (i[10] += s * s),
              (i[11] += s * f),
              (i[15] += f * f));
          }
          return (
            (i[4] = i[1]),
            (i[8] = i[2]),
            (i[9] = i[6]),
            (i[12] = i[3]),
            (i[13] = i[7]),
            (i[14] = i[11]),
            { R: i, m: o, N: a }
          );
        }
        function estats(e) {
          const { R: t } = e,
            { m: r } = e,
            { N: i } = e,
            a = r[0],
            s = r[1],
            f = r[2],
            l = r[3],
            c = 0 == i ? 0 : 1 / i,
            u = [
              t[0] - a * a * c,
              t[1] - a * s * c,
              t[2] - a * f * c,
              t[3] - a * l * c,
              t[4] - s * a * c,
              t[5] - s * s * c,
              t[6] - s * f * c,
              t[7] - s * l * c,
              t[8] - f * a * c,
              t[9] - f * s * c,
              t[10] - f * f * c,
              t[11] - f * l * c,
              t[12] - l * a * c,
              t[13] - l * s * c,
              t[14] - l * f * c,
              t[15] - l * l * c,
            ],
            h = u,
            d = o;
          let A = [Math.random(), Math.random(), Math.random(), Math.random()],
            g = 0,
            p = 0;
          if (0 != i)
            for (
              let e = 0;
              e < 16 &&
              ((A = d.multVec(h, A)),
              (p = Math.sqrt(d.dot(A, A))),
              (A = d.sml(1 / p, A)),
              !(0 != e && Math.abs(p - g) < 1e-9));
              e++
            )
              g = p;
          const m = [a * c, s * c, f * c, l * c];
          return {
            Cov: u,
            q: m,
            e: A,
            L: g,
            eMq255: d.dot(d.sml(255, m), A),
            eMq: d.dot(A, m),
            rgba:
              ((Math.round(255 * m[3]) << 24) |
                (Math.round(255 * m[2]) << 16) |
                (Math.round(255 * m[1]) << 8) |
                (Math.round(255 * m[0]) << 0)) >>>
              0,
          };
        }
        var o = {
          multVec: (e, t) => [
            e[0] * t[0] + e[1] * t[1] + e[2] * t[2] + e[3] * t[3],
            e[4] * t[0] + e[5] * t[1] + e[6] * t[2] + e[7] * t[3],
            e[8] * t[0] + e[9] * t[1] + e[10] * t[2] + e[11] * t[3],
            e[12] * t[0] + e[13] * t[1] + e[14] * t[2] + e[15] * t[3],
          ],
          dot: (e, t) => e[0] * t[0] + e[1] * t[1] + e[2] * t[2] + e[3] * t[3],
          sml: (e, t) => [e * t[0], e * t[1], e * t[2], e * t[3]],
        };
        ((UPNG.encode = function encode(e, t, r, i, o, a, s) {
          (null == i && (i = 0), null == s && (s = !1));
          const f = compress(e, t, r, i, [!1, !1, !1, 0, s, !1]);
          return (compressPNG(f, -1), _main(f, t, r, o, a));
        }),
          (UPNG.encodeLL = function encodeLL(e, t, r, i, o, a, s, f) {
            const l = { ctype: 0 + (1 == i ? 0 : 2) + (0 == o ? 0 : 4), depth: a, frames: [] },
              c = (i + o) * a,
              u = c * t;
            for (let i = 0; i < e.length; i++)
              l.frames.push({
                rect: { x: 0, y: 0, width: t, height: r },
                img: new Uint8Array(e[i]),
                blend: 0,
                dispose: 1,
                bpp: Math.ceil(c / 8),
                bpl: Math.ceil(u / 8),
              });
            return (compressPNG(l, 0, !0), _main(l, t, r, s, f));
          }),
          (UPNG.encode.compress = compress),
          (UPNG.encode.dither = dither),
          (UPNG.quantize = quantize),
          (UPNG.quantize.getKDtree = getKDtree),
          (UPNG.quantize.getNearest = getNearest));
      })();
      const t = {
        toArrayBuffer(e, r) {
          const i = e.width,
            o = e.height,
            a = i << 2,
            s = e.getContext('2d').getImageData(0, 0, i, o),
            f = new Uint32Array(s.data.buffer),
            l = ((32 * i + 31) / 32) << 2,
            c = l * o,
            u = 122 + c,
            h = new ArrayBuffer(u),
            d = new DataView(h),
            A = 1 << 20;
          let g,
            p,
            m,
            w,
            v = A,
            b = 0,
            y = 0,
            E = 0;
          function set16(e) {
            (d.setUint16(y, e, !0), (y += 2));
          }
          function set32(e) {
            (d.setUint32(y, e, !0), (y += 4));
          }
          function seek(e) {
            y += e;
          }
          (set16(19778),
            set32(u),
            seek(4),
            set32(122),
            set32(108),
            set32(i),
            set32(-o >>> 0),
            set16(1),
            set16(32),
            set32(3),
            set32(c),
            set32(2835),
            set32(2835),
            seek(8),
            set32(16711680),
            set32(65280),
            set32(255),
            set32(4278190080),
            set32(1466527264),
            (function convert() {
              for (; b < o && v > 0; ) {
                for (w = 122 + b * l, g = 0; g < a; )
                  (v--, (p = f[E++]), (m = p >>> 24), d.setUint32(w + g, (p << 8) | m), (g += 4));
                b++;
              }
              E < f.length ? ((v = A), setTimeout(convert, t._dly)) : r(h);
            })());
        },
        toBlob(e, t) {
          this.toArrayBuffer(e, (e) => {
            t(new Blob([e], { type: 'image/bmp' }));
          });
        },
        _dly: 9,
      };
      var r = {
          CHROME: 'CHROME',
          FIREFOX: 'FIREFOX',
          DESKTOP_SAFARI: 'DESKTOP_SAFARI',
          IE: 'IE',
          IOS: 'IOS',
          ETC: 'ETC',
        },
        i = {
          [r.CHROME]: 16384,
          [r.FIREFOX]: 11180,
          [r.DESKTOP_SAFARI]: 16384,
          [r.IE]: 8192,
          [r.IOS]: 4096,
          [r.ETC]: 8192,
        };
      const o = 'undefined' != typeof window,
        a = 'undefined' != typeof WorkerGlobalScope && self instanceof WorkerGlobalScope,
        s = o && window.cordova && window.cordova.require && window.cordova.require('cordova/modulemapper'),
        CustomFile = (o || a) && ((s && s.getOriginalSymbol(window, 'File')) || ('undefined' != typeof File && File)),
        CustomFileReader =
          (o || a) &&
          ((s && s.getOriginalSymbol(window, 'FileReader')) || ('undefined' != typeof FileReader && FileReader));
      function getFilefromDataUrl(e, t, r = Date.now()) {
        return new Promise((i) => {
          const o = e.split(','),
            a = o[0].match(/:(.*?);/)[1],
            s = globalThis.atob(o[1]);
          let f = s.length;
          const l = new Uint8Array(f);
          for (; f--; ) l[f] = s.charCodeAt(f);
          const c = new Blob([l], { type: a });
          ((c.name = t), (c.lastModified = r), i(c));
        });
      }
      function getDataUrlFromFile(e) {
        return new Promise((t, r) => {
          const i = new CustomFileReader();
          ((i.onload = () => t(i.result)), (i.onerror = (e) => r(e)), i.readAsDataURL(e));
        });
      }
      function loadImage(e) {
        return new Promise((t, r) => {
          const i = new Image();
          ((i.onload = () => t(i)), (i.onerror = (e) => r(e)), (i.src = e));
        });
      }
      function getBrowserName() {
        if (void 0 !== getBrowserName.cachedResult) return getBrowserName.cachedResult;
        let e = r.ETC;
        const { userAgent: t } = navigator;
        return (
          /Chrom(e|ium)/i.test(t)
            ? (e = r.CHROME)
            : /iP(ad|od|hone)/i.test(t) && /WebKit/i.test(t)
              ? (e = r.IOS)
              : /Safari/i.test(t)
                ? (e = r.DESKTOP_SAFARI)
                : /Firefox/i.test(t)
                  ? (e = r.FIREFOX)
                  : (/MSIE/i.test(t) || !0 == !!document.documentMode) && (e = r.IE),
          (getBrowserName.cachedResult = e),
          getBrowserName.cachedResult
        );
      }
      function approximateBelowMaximumCanvasSizeOfBrowser(e, t) {
        const r = getBrowserName(),
          o = i[r];
        let a = e,
          s = t,
          f = a * s;
        const l = a > s ? s / a : a / s;
        for (; f > o * o; ) {
          const e = (o + a) / 2,
            t = (o + s) / 2;
          (e < t ? ((s = t), (a = t * l)) : ((s = e * l), (a = e)), (f = a * s));
        }
        return { width: a, height: s };
      }
      function getNewCanvasAndCtx(e, t) {
        let r, i;
        try {
          if (((r = new OffscreenCanvas(e, t)), (i = r.getContext('2d')), null === i))
            throw new Error('getContext of OffscreenCanvas returns null');
        } catch (e) {
          ((r = document.createElement('canvas')), (i = r.getContext('2d')));
        }
        return ((r.width = e), (r.height = t), [r, i]);
      }
      function drawImageInCanvas(e, t) {
        const { width: r, height: i } = approximateBelowMaximumCanvasSizeOfBrowser(e.width, e.height),
          [o, a] = getNewCanvasAndCtx(r, i);
        return (
          t && /jpe?g/.test(t) && ((a.fillStyle = 'white'), a.fillRect(0, 0, o.width, o.height)),
          a.drawImage(e, 0, 0, o.width, o.height),
          o
        );
      }
      function isIOS() {
        return (
          void 0 !== isIOS.cachedResult ||
            (isIOS.cachedResult =
              ['iPad Simulator', 'iPhone Simulator', 'iPod Simulator', 'iPad', 'iPhone', 'iPod'].includes(
                navigator.platform,
              ) ||
              (navigator.userAgent.includes('Mac') && 'undefined' != typeof document && 'ontouchend' in document)),
          isIOS.cachedResult
        );
      }
      function drawFileInCanvas(e, t = {}) {
        return new Promise(function (i, o) {
          let a, s;
          var $Try_2_Post = function () {
              try {
                return ((s = drawImageInCanvas(a, t.fileType || e.type)), i([a, s]));
              } catch (e) {
                return o(e);
              }
            },
            $Try_2_Catch = function (t) {
              try {
                0;
                var $Try_3_Catch = function (e) {
                  try {
                    throw e;
                  } catch (e) {
                    return o(e);
                  }
                };
                try {
                  let t;
                  return getDataUrlFromFile(e).then(function (e) {
                    try {
                      return (
                        (t = e),
                        loadImage(t).then(function (e) {
                          try {
                            return (
                              (a = e),
                              (function () {
                                try {
                                  return $Try_2_Post();
                                } catch (e) {
                                  return o(e);
                                }
                              })()
                            );
                          } catch (e) {
                            return $Try_3_Catch(e);
                          }
                        }, $Try_3_Catch)
                      );
                    } catch (e) {
                      return $Try_3_Catch(e);
                    }
                  }, $Try_3_Catch);
                } catch (e) {
                  $Try_3_Catch(e);
                }
              } catch (e) {
                return o(e);
              }
            };
          try {
            if (isIOS() || [r.DESKTOP_SAFARI, r.MOBILE_SAFARI].includes(getBrowserName()))
              throw new Error('Skip createImageBitmap on IOS and Safari');
            return createImageBitmap(e).then(function (e) {
              try {
                return ((a = e), $Try_2_Post());
              } catch (e) {
                return $Try_2_Catch();
              }
            }, $Try_2_Catch);
          } catch (e) {
            $Try_2_Catch();
          }
        });
      }
      function canvasToFile(e, r, i, o, a = 1) {
        return new Promise(function (s, f) {
          let l;
          if ('image/png' === r) {
            let c, u, h;
            return (
              (c = e.getContext('2d')),
              ({ data: u } = c.getImageData(0, 0, e.width, e.height)),
              (h = UPNG.encode([u.buffer], e.width, e.height, 4096 * a)),
              (l = new Blob([h], { type: r })),
              (l.name = i),
              (l.lastModified = o),
              $If_4.call(this)
            );
          }
          {
            if ('image/bmp' === r)
              return new Promise((r) => t.toBlob(e, r)).then(
                function (e) {
                  try {
                    return ((l = e), (l.name = i), (l.lastModified = o), $If_5.call(this));
                  } catch (e) {
                    return f(e);
                  }
                }.bind(this),
                f,
              );
            {
              if ('function' == typeof OffscreenCanvas && e instanceof OffscreenCanvas)
                return e.convertToBlob({ type: r, quality: a }).then(
                  function (e) {
                    try {
                      return ((l = e), (l.name = i), (l.lastModified = o), $If_6.call(this));
                    } catch (e) {
                      return f(e);
                    }
                  }.bind(this),
                  f,
                );
              {
                let d;
                return (
                  (d = e.toDataURL(r, a)),
                  getFilefromDataUrl(d, i, o).then(
                    function (e) {
                      try {
                        return ((l = e), $If_6.call(this));
                      } catch (e) {
                        return f(e);
                      }
                    }.bind(this),
                    f,
                  )
                );
              }
              function $If_6() {
                return $If_5.call(this);
              }
            }
            function $If_5() {
              return $If_4.call(this);
            }
          }
          function $If_4() {
            return s(l);
          }
        });
      }
      function cleanupCanvasMemory(e) {
        ((e.width = 0), (e.height = 0));
      }
      function isAutoOrientationInBrowser() {
        return new Promise(function (e, t) {
          let r, i, o, a, s;
          return void 0 !== isAutoOrientationInBrowser.cachedResult
            ? e(isAutoOrientationInBrowser.cachedResult)
            : ((r =
                ''),
              getFilefromDataUrl(
                '',
                'test.jpg',
                Date.now(),
              ).then(function (r) {
                try {
                  return (
                    (i = r),
                    drawFileInCanvas(i).then(function (r) {
                      try {
                        return (
                          (o = r[1]),
                          canvasToFile(o, i.type, i.name, i.lastModified).then(function (r) {
                            try {
                              return (
                                (a = r),
                                cleanupCanvasMemory(o),
                                drawFileInCanvas(a).then(function (r) {
                                  try {
                                    return (
                                      (s = r[0]),
                                      (isAutoOrientationInBrowser.cachedResult = 1 === s.width && 2 === s.height),
                                      e(isAutoOrientationInBrowser.cachedResult)
                                    );
                                  } catch (e) {
                                    return t(e);
                                  }
                                }, t)
                              );
                            } catch (e) {
                              return t(e);
                            }
                          }, t)
                        );
                      } catch (e) {
                        return t(e);
                      }
                    }, t)
                  );
                } catch (e) {
                  return t(e);
                }
              }, t));
        });
      }
      function getExifOrientation(e) {
        return new Promise((t, r) => {
          const i = new CustomFileReader();
          ((i.onload = (e) => {
            const r = new DataView(e.target.result);
            if (65496 != r.getUint16(0, !1)) return t(-2);
            const i = r.byteLength;
            let o = 2;
            for (; o < i; ) {
              if (r.getUint16(o + 2, !1) <= 8) return t(-1);
              const e = r.getUint16(o, !1);
              if (((o += 2), 65505 == e)) {
                if (1165519206 != r.getUint32((o += 2), !1)) return t(-1);
                const e = 18761 == r.getUint16((o += 6), !1);
                o += r.getUint32(o + 4, e);
                const i = r.getUint16(o, e);
                o += 2;
                for (let a = 0; a < i; a++)
                  if (274 == r.getUint16(o + 12 * a, e)) return t(r.getUint16(o + 12 * a + 8, e));
              } else {
                if (65280 != (65280 & e)) break;
                o += r.getUint16(o, !1);
              }
            }
            return t(-1);
          }),
            (i.onerror = (e) => r(e)),
            i.readAsArrayBuffer(e));
        });
      }
      function handleMaxWidthOrHeight(e, t) {
        const { width: r } = e,
          { height: i } = e,
          { maxWidthOrHeight: o } = t;
        let a,
          s = e;
        return (
          isFinite(o) &&
            (r > o || i > o) &&
            (([s, a] = getNewCanvasAndCtx(r, i)),
            r > i ? ((s.width = o), (s.height = (i / r) * o)) : ((s.width = (r / i) * o), (s.height = o)),
            a.drawImage(e, 0, 0, s.width, s.height),
            cleanupCanvasMemory(e)),
          s
        );
      }
      function followExifOrientation(e, t) {
        const { width: r } = e,
          { height: i } = e,
          [o, a] = getNewCanvasAndCtx(r, i);
        switch ((t > 4 && t < 9 ? ((o.width = i), (o.height = r)) : ((o.width = r), (o.height = i)), t)) {
          case 2:
            a.transform(-1, 0, 0, 1, r, 0);
            break;
          case 3:
            a.transform(-1, 0, 0, -1, r, i);
            break;
          case 4:
            a.transform(1, 0, 0, -1, 0, i);
            break;
          case 5:
            a.transform(0, 1, 1, 0, 0, 0);
            break;
          case 6:
            a.transform(0, 1, -1, 0, i, 0);
            break;
          case 7:
            a.transform(0, -1, -1, 0, i, r);
            break;
          case 8:
            a.transform(0, -1, 1, 0, 0, r);
        }
        return (a.drawImage(e, 0, 0, r, i), cleanupCanvasMemory(e), o);
      }
      function compress(e, t, r = 0) {
        return new Promise(function (i, o) {
          let a, s, f, l, c, u, h, d, A, g, p, m, w, v, b, y, E, F, _, B;
          function incProgress(e = 5) {
            if (t.signal && t.signal.aborted) throw t.signal.reason;
            ((a += e), t.onProgress(Math.min(a, 100)));
          }
          function setProgress(e) {
            if (t.signal && t.signal.aborted) throw t.signal.reason;
            ((a = Math.min(Math.max(e, a), 100)), t.onProgress(a));
          }
          return (
            (a = r),
            (s = t.maxIteration || 10),
            (f = 1024 * t.maxSizeMB * 1024),
            incProgress(),
            drawFileInCanvas(e, t).then(
              function (r) {
                try {
                  return (
                    ([, l] = r),
                    incProgress(),
                    (c = handleMaxWidthOrHeight(l, t)),
                    incProgress(),
                    new Promise(function (r, i) {
                      var o;
                      if (!(o = t.exifOrientation))
                        return getExifOrientation(e).then(
                          function (e) {
                            try {
                              return ((o = e), $If_2.call(this));
                            } catch (e) {
                              return i(e);
                            }
                          }.bind(this),
                          i,
                        );
                      function $If_2() {
                        return r(o);
                      }
                      return $If_2.call(this);
                    }).then(
                      function (r) {
                        try {
                          return (
                            (u = r),
                            incProgress(),
                            isAutoOrientationInBrowser().then(
                              function (r) {
                                try {
                                  return (
                                    (h = r ? c : followExifOrientation(c, u)),
                                    incProgress(),
                                    (d = t.initialQuality || 1),
                                    (A = t.fileType || e.type),
                                    canvasToFile(h, A, e.name, e.lastModified, d).then(
                                      function (r) {
                                        try {
                                          {
                                            if (
                                              ((g = r),
                                              incProgress(),
                                              (p = g.size > f),
                                              (m = g.size > e.size),
                                              !p && !m)
                                            )
                                              return (setProgress(100), i(g));
                                            var a;
                                            function $Loop_3() {
                                              if (s-- && (b > f || b > w)) {
                                                let t, r;
                                                return (
                                                  (t = B ? 0.95 * _.width : _.width),
                                                  (r = B ? 0.95 * _.height : _.height),
                                                  ([E, F] = getNewCanvasAndCtx(t, r)),
                                                  F.drawImage(_, 0, 0, t, r),
                                                  (d *= 'image/png' === A ? 0.85 : 0.95),
                                                  canvasToFile(E, A, e.name, e.lastModified, d).then(function (e) {
                                                    try {
                                                      return (
                                                        (y = e),
                                                        cleanupCanvasMemory(_),
                                                        (_ = E),
                                                        (b = y.size),
                                                        setProgress(
                                                          Math.min(99, Math.floor(((v - b) / (v - f)) * 100)),
                                                        ),
                                                        $Loop_3
                                                      );
                                                    } catch (e) {
                                                      return o(e);
                                                    }
                                                  }, o)
                                                );
                                              }
                                              return [1];
                                            }
                                            return (
                                              (w = e.size),
                                              (v = g.size),
                                              (b = v),
                                              (_ = h),
                                              (B = !t.alwaysKeepResolution && p),
                                              (a = function (e) {
                                                for (; e; ) {
                                                  if (e.then) return void e.then(a, o);
                                                  try {
                                                    if (e.pop) {
                                                      if (e.length) return e.pop() ? $Loop_3_exit.call(this) : e;
                                                      e = $Loop_3;
                                                    } else e = e.call(this);
                                                  } catch (e) {
                                                    return o(e);
                                                  }
                                                }
                                              }.bind(this))($Loop_3)
                                            );
                                            function $Loop_3_exit() {
                                              return (
                                                cleanupCanvasMemory(_),
                                                cleanupCanvasMemory(E),
                                                cleanupCanvasMemory(c),
                                                cleanupCanvasMemory(h),
                                                cleanupCanvasMemory(l),
                                                setProgress(100),
                                                i(y)
                                              );
                                            }
                                          }
                                        } catch (u) {
                                          return o(u);
                                        }
                                      }.bind(this),
                                      o,
                                    )
                                  );
                                } catch (e) {
                                  return o(e);
                                }
                              }.bind(this),
                              o,
                            )
                          );
                        } catch (e) {
                          return o(e);
                        }
                      }.bind(this),
                      o,
                    )
                  );
                } catch (e) {
                  return o(e);
                }
              }.bind(this),
              o,
            )
          );
        });
      }
      const f =
        "\nlet scriptImported = false\nself.addEventListener('message', async (e) => {\n  const { file, id, imageCompressionLibUrl, options } = e.data\n  options.onProgress = (progress) => self.postMessage({ progress, id })\n  try {\n    if (!scriptImported) {\n      // console.log('[worker] importScripts', imageCompressionLibUrl)\n      self.importScripts(imageCompressionLibUrl)\n      scriptImported = true\n    }\n    // console.log('[worker] self', self)\n    const compressedFile = await imageCompression(file, options)\n    self.postMessage({ file: compressedFile, id })\n  } catch (e) {\n    // console.error('[worker] error', e)\n    self.postMessage({ error: e.message + '\\n' + e.stack, id })\n  }\n})\n";
      let l;
      function compressOnWebWorker(e, t) {
        return new Promise((r, i) => {
          l ||
            (l = (function createWorkerScriptURL(e) {
              const t = [];
              return ('function' == typeof e ? t.push(`(${e})()`) : t.push(e), URL.createObjectURL(new Blob(t)));
            })(f));
          const o = new Worker(l);
          (o.addEventListener('message', function handler(e) {
            if (t.signal && t.signal.aborted) o.terminate();
            else if (void 0 === e.data.progress) {
              if (e.data.error) return (i(new Error(e.data.error)), void o.terminate());
              (r(e.data.file), o.terminate());
            } else t.onProgress(e.data.progress);
          }),
            o.addEventListener('error', i),
            t.signal &&
              t.signal.addEventListener('abort', () => {
                (i(t.signal.reason), o.terminate());
              }),
            o.postMessage({
              file: e,
              imageCompressionLibUrl: t.libURL,
              options: { ...t, onProgress: void 0, signal: void 0 },
            }));
        });
      }
      function imageCompression(e, t) {
        return new Promise(function (r, i) {
          let o, a, s, f, l, c;
          if (
            ((o = { ...t }),
            (s = 0),
            ({ onProgress: f } = o),
            (o.maxSizeMB = o.maxSizeMB || Number.POSITIVE_INFINITY),
            (l = 'boolean' != typeof o.useWebWorker || o.useWebWorker),
            delete o.useWebWorker,
            (o.onProgress = (e) => {
              ((s = e), 'function' == typeof f && f(s));
            }),
            !(1 || e instanceof Blob || e instanceof CustomFile))
          )
            return i(new Error('The file given is not an instance of Blob or File'));
          if (!/^image/.test(e.type)) return i(new Error('The file given is not an image'));
          if (
            ((c = 'undefined' != typeof WorkerGlobalScope && self instanceof WorkerGlobalScope),
            !l || 'function' != typeof Worker || c)
          )
            return compress(e, o).then(
              function (e) {
                try {
                  return ((a = e), $If_4.call(this));
                } catch (e) {
                  return i(e);
                }
              }.bind(this),
              i,
            );
          var u = function () {
              try {
                return $If_4.call(this);
              } catch (e) {
                return i(e);
              }
            }.bind(this),
            $Try_1_Catch = function (t) {
              try {
                return compress(e, o).then(function (e) {
                  try {
                    return ((a = e), u());
                  } catch (e) {
                    return i(e);
                  }
                }, i);
              } catch (e) {
                return i(e);
              }
            };
          try {
            return (
              (o.libURL =
                o.libURL ||
                'https://cdn.bootcdn.net/ajax/libs/browser-image-compression/2.0.2/browser-image-compression.js'),
              compressOnWebWorker(e, o).then(function (e) {
                try {
                  return ((a = e), u());
                } catch (e) {
                  return $Try_1_Catch();
                }
              }, $Try_1_Catch)
            );
          } catch (e) {
            $Try_1_Catch();
          }
          function $If_4() {
            try {
              ((a.name = e.name), (a.lastModified = e.lastModified));
            } catch (e) {}
            try {
              o.preserveExif &&
                'image/jpeg' === e.type &&
                (!o.fileType || (o.fileType && o.fileType === e.type)) &&
                (a = copyExifWithoutOrientation(e, a));
            } catch (e) {}
            return r(a);
          }
        });
      }
      return (
        (imageCompression.getDataUrlFromFile = getDataUrlFromFile),
        (imageCompression.getFilefromDataUrl = getFilefromDataUrl),
        (imageCompression.loadImage = loadImage),
        (imageCompression.drawImageInCanvas = drawImageInCanvas),
        (imageCompression.drawFileInCanvas = drawFileInCanvas),
        (imageCompression.canvasToFile = canvasToFile),
        (imageCompression.getExifOrientation = getExifOrientation),
        (imageCompression.handleMaxWidthOrHeight = handleMaxWidthOrHeight),
        (imageCompression.followExifOrientation = followExifOrientation),
        (imageCompression.cleanupCanvasMemory = cleanupCanvasMemory),
        (imageCompression.isAutoOrientationInBrowser = isAutoOrientationInBrowser),
        (imageCompression.approximateBelowMaximumCanvasSizeOfBrowser = approximateBelowMaximumCanvasSizeOfBrowser),
        (imageCompression.copyExifWithoutOrientation = copyExifWithoutOrientation),
        (imageCompression.getBrowserName = getBrowserName),
        (imageCompression.version = '2.0.2'),
        imageCompression
      );
    });
    return {
      compress: function (file, option) {
        return imageCompression(file, option);
      },
    };
  })();
  UE.dialog = (function () {
    return {
      loadingPlaceholder: function (me) {
        var loadingId = 'loading_' + (+new Date()).toString(36);
        me.focus();
        me.execCommand(
          'inserthtml',
          '<img class="uep-loading" id="' +
            loadingId +
            '" src="' +
            me.options.themePath +
            me.options.theme +
            '/images/spacer.gif">',
        );
        return loadingId;
      },
      removeLoadingPlaceholder: function (me, loadingId) {
        var loader = me.document.getElementById(loadingId);
        if (loader) {
          domUtils.remove(loader, false);
        }
      },
      tipError: function (me, title) {
        me.fireEvent('showmessage', { content: title, type: 'error', timeout: 4e3 });
      },
    };
  })();
  var filterWord = (UE.filterWord = (function () {
    function isWordDocument(str) {
      return /(class="?Mso|style="[^"]*\bmso\-|w:WordDocument|<(v|o):|lang=)/gi.test(str);
    }
    function transUnit(v) {
      v = v.replace(/[\d.]+\w+/g, function (m) {
        return utils.transUnitToPx(m);
      });
      return v;
    }
    function filterPasteWord(str) {
      return str
        .replace(/[\t\r\n]+/g, ' ')
        .replace(/<!--[\s\S]*?-->/gi, '')
        .replace(/<v:shape [^>]*>[\s\S]*?.<\/v:shape>/gi, function (str) {
          if (browser.opera) {
            return '';
          }
          try {
            if (/Bitmap/i.test(str)) {
              return '';
            }
            var width = str.match(/width:([ \d.]*p[tx])/i)[1],
              height = str.match(/height:([ \d.]*p[tx])/i)[1],
              src = str.match(/src=\s*"([^"]*)"/i)[1];
            return '<img width="' + transUnit(width) + '" height="' + transUnit(height) + '" src="' + src + '" />';
          } catch (e) {
            return '';
          }
        })
        .replace(/<\/?div[^>]*>/g, '')
        .replace(/v:\w+=(["']?)[^'"]+\1/g, '')
        .replace(
          /<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|xml|meta|link|style|\w+:\w+)(?=[\s\/>]))[^>]*>/gi,
          '',
        )
        .replace(/<p [^>]*class="?MsoHeading"?[^>]*>(.*?)<\/p>/gi, '<p><strong>$1</strong></p>')
        .replace(/\s+(class|lang|align)\s*=\s*(['"]?)([\w-]+)\2/gi, function (str, name, marks, val) {
          return name == 'class' && val == 'MsoListParagraph' ? str : '';
        })
        .replace(/<(font|span)[^>]*>(\s*)<\/\1>/gi, function (a, b, c) {
          return c.replace(/[\t\r\n ]+/g, ' ');
        })
        .replace(/(<[a-z][^>]*)\sstyle=(["'])([^\2]*?)\2/gi, function (str, tag, tmp, style) {
          var n = [],
            s = style
              .replace(/^\s+|\s+$/, '')
              .replace(/&#39;/g, "'")
              .replace(/&quot;/gi, "'")
              .replace(/[\d.]+(cm|pt)/g, function (str) {
                return utils.transUnitToPx(str);
              })
              .split(/;\s*/g);
          for (var i = 0, v; (v = s[i]); i++) {
            var name,
              value,
              parts = v.split(':');
            if (parts.length == 2) {
              name = parts[0].toLowerCase();
              value = parts[1].toLowerCase();
              if (
                (/^(background)\w*/.test(name) && value.replace(/(initial|\s)/g, '').length == 0) ||
                (/^(margin)\w*/.test(name) && /^0\w+$/.test(value))
              ) {
                continue;
              }
              switch (name) {
                case 'mso-padding-alt':
                case 'mso-padding-top-alt':
                case 'mso-padding-right-alt':
                case 'mso-padding-bottom-alt':
                case 'mso-padding-left-alt':
                case 'mso-margin-alt':
                case 'mso-margin-top-alt':
                case 'mso-margin-right-alt':
                case 'mso-margin-bottom-alt':
                case 'mso-margin-left-alt':
                case 'mso-height':
                case 'mso-width':
                case 'mso-vertical-align-alt':
                  if (!/<table/.test(tag)) n[i] = name.replace(/^mso-|-alt$/g, '') + ':' + transUnit(value);
                  continue;
                case 'horiz-align':
                  n[i] = 'text-align:' + value;
                  continue;
                case 'vert-align':
                  n[i] = 'vertical-align:' + value;
                  continue;
                case 'font-color':
                case 'mso-foreground':
                  n[i] = 'color:' + value;
                  continue;
                case 'mso-background':
                case 'mso-highlight':
                  n[i] = 'background:' + value;
                  continue;
                case 'mso-default-height':
                  n[i] = 'min-height:' + transUnit(value);
                  continue;
                case 'mso-default-width':
                  n[i] = 'min-width:' + transUnit(value);
                  continue;
                case 'mso-padding-between-alt':
                  n[i] = 'border-collapse:separate;border-spacing:' + transUnit(value);
                  continue;
                case 'text-line-through':
                  if (value == 'single' || value == 'double') {
                    n[i] = 'text-decoration:line-through';
                  }
                  continue;
                case 'mso-zero-height':
                  if (value == 'yes') {
                    n[i] = 'display:none';
                  }
                  continue;
                case 'margin':
                  if (!/[1-9]/.test(value)) {
                    continue;
                  }
              }
              if (
                /^(mso|column|font-emph|lang|layout|line-break|list-image|nav|panose|punct|row|ruby|sep|size|src|tab-|table-border|text-(?:decor|trans)|top-bar|version|vnd|word-break)/.test(
                  name,
                ) ||
                (/text\-indent|padding|margin/.test(name) && /\-[\d.]+/.test(value))
              ) {
                continue;
              }
              n[i] = name + ':' + parts[1];
            }
          }
          return tag + (n.length ? ' style="' + n.join(';').replace(/;{2,}/g, ';') + '"' : '');
        });
    }
    return function (html) {
      return isWordDocument(html) ? filterPasteWord(html) : html;
    };
  })());
  (function () {
    var uNode = (UE.uNode = function (obj) {
      this.type = obj.type;
      this.data = obj.data;
      this.tagName = obj.tagName;
      this.parentNode = obj.parentNode;
      this.attrs = obj.attrs || {};
      this.children = obj.children;
    });
    var notTransAttrs = { href: 1, src: 1, _src: 1, _href: 1, cdata_data: 1 };
    var notTransTagName = { style: 1, script: 1 };
    var indentChar = '    ',
      breakChar = '\n';
    function insertLine(arr, current, begin) {
      arr.push(breakChar);
      return current + (begin ? 1 : -1);
    }
    function insertIndent(arr, current) {
      for (var i = 0; i < current; i++) {
        arr.push(indentChar);
      }
    }
    uNode.createElement = function (html) {
      if (/[<>]/.test(html)) {
        return UE.htmlparser(html).children[0];
      } else {
        return new uNode({ type: 'element', children: [], tagName: html });
      }
    };
    uNode.createText = function (data, noTrans) {
      return new UE.uNode({ type: 'text', data: noTrans ? data : utils.unhtml(data || '') });
    };
    function nodeToHtml(node, arr, formatter, current) {
      switch (node.type) {
        case 'root':
          for (var i = 0, ci; (ci = node.children[i++]); ) {
            if (formatter && ci.type == 'element' && !dtd.$inlineWithA[ci.tagName] && i > 1) {
              insertLine(arr, current, true);
              insertIndent(arr, current);
            }
            nodeToHtml(ci, arr, formatter, current);
          }
          break;
        case 'text':
          isText(node, arr);
          break;
        case 'element':
          isElement(node, arr, formatter, current);
          break;
        case 'comment':
          isComment(node, arr, formatter);
      }
      return arr;
    }
    function isText(node, arr) {
      if (node.parentNode.tagName == 'pre') {
        arr.push(node.data);
      } else {
        arr.push(
          notTransTagName[node.parentNode.tagName] ? utils.html(node.data) : node.data.replace(/[ ]{2}/g, ' &nbsp;'),
        );
      }
    }
    function isElement(node, arr, formatter, current) {
      var attrhtml = '';
      if (node.attrs) {
        attrhtml = [];
        var attrs = node.attrs;
        for (var a in attrs) {
          attrhtml.push(
            a +
              (attrs[a] !== undefined
                ? '="' +
                  (notTransAttrs[a]
                    ? utils.html(attrs[a]).replace(/["]/g, function (a) {
                        return '&quot;';
                      })
                    : utils.unhtml(attrs[a])) +
                  '"'
                : ''),
          );
        }
        attrhtml = attrhtml.join(' ');
      }
      arr.push('<' + node.tagName + (attrhtml ? ' ' + attrhtml : '') + (dtd.$empty[node.tagName] ? '/' : '') + '>');
      if (formatter && !dtd.$inlineWithA[node.tagName] && node.tagName != 'pre') {
        if (node.children && node.children.length) {
          current = insertLine(arr, current, true);
          insertIndent(arr, current);
        }
      }
      if (node.children && node.children.length) {
        for (var i = 0, ci; (ci = node.children[i++]); ) {
          if (formatter && ci.type == 'element' && !dtd.$inlineWithA[ci.tagName] && i > 1) {
            insertLine(arr, current);
            insertIndent(arr, current);
          }
          nodeToHtml(ci, arr, formatter, current);
        }
      }
      if (!dtd.$empty[node.tagName]) {
        if (formatter && !dtd.$inlineWithA[node.tagName] && node.tagName != 'pre') {
          if (node.children && node.children.length) {
            current = insertLine(arr, current);
            insertIndent(arr, current);
          }
        }
        arr.push('</' + node.tagName + '>');
      }
    }
    function isComment(node, arr) {
      arr.push('\x3c!--' + node.data + '--\x3e');
    }
    function getNodeById(root, id) {
      var node;
      if (root.type == 'element' && root.getAttr('id') == id) {
        return root;
      }
      if (root.children && root.children.length) {
        for (var i = 0, ci; (ci = root.children[i++]); ) {
          if ((node = getNodeById(ci, id))) {
            return node;
          }
        }
      }
    }
    function getNodesByTagName(node, tagName, arr) {
      if (node.type == 'element' && node.tagName == tagName) {
        arr.push(node);
      }
      if (node.children && node.children.length) {
        for (var i = 0, ci; (ci = node.children[i++]); ) {
          getNodesByTagName(ci, tagName, arr);
        }
      }
    }
    function nodeTraversal(root, fn) {
      if (root.children && root.children.length) {
        for (var i = 0, ci; (ci = root.children[i]); ) {
          nodeTraversal(ci, fn);
          if (ci.parentNode) {
            if (ci.children && ci.children.length) {
              fn(ci);
            }
            if (ci.parentNode) i++;
          }
        }
      } else {
        fn(root);
      }
    }
    uNode.prototype = {
      toHtml: function (formatter) {
        var arr = [];
        nodeToHtml(this, arr, formatter, 0);
        return arr.join('');
      },
      innerHTML: function (htmlstr) {
        if (this.type != 'element' || dtd.$empty[this.tagName]) {
          return this;
        }
        if (utils.isString(htmlstr)) {
          if (this.children) {
            for (var i = 0, ci; (ci = this.children[i++]); ) {
              ci.parentNode = null;
            }
          }
          this.children = [];
          var tmpRoot = UE.htmlparser(htmlstr);
          for (var i = 0, ci; (ci = tmpRoot.children[i++]); ) {
            this.children.push(ci);
            ci.parentNode = this;
          }
          return this;
        } else {
          var tmpRoot = new UE.uNode({ type: 'root', children: this.children });
          return tmpRoot.toHtml();
        }
      },
      innerText: function (textStr, noTrans) {
        if (this.type != 'element' || dtd.$empty[this.tagName]) {
          return this;
        }
        if (textStr) {
          if (this.children) {
            for (var i = 0, ci; (ci = this.children[i++]); ) {
              ci.parentNode = null;
            }
          }
          this.children = [];
          this.appendChild(uNode.createText(textStr, noTrans));
          return this;
        } else {
          return this.toHtml().replace(/<[^>]+>/g, '');
        }
      },
      getData: function () {
        if (this.type == 'element') return '';
        return this.data;
      },
      firstChild: function () {
        return this.children ? this.children[0] : null;
      },
      lastChild: function () {
        return this.children ? this.children[this.children.length - 1] : null;
      },
      previousSibling: function () {
        var parent = this.parentNode;
        for (var i = 0, ci; (ci = parent.children[i]); i++) {
          if (ci === this) {
            return i == 0 ? null : parent.children[i - 1];
          }
        }
      },
      nextSibling: function () {
        var parent = this.parentNode;
        for (var i = 0, ci; (ci = parent.children[i++]); ) {
          if (ci === this) {
            return parent.children[i];
          }
        }
      },
      replaceChild: function (target, source) {
        if (this.children) {
          if (target.parentNode) {
            target.parentNode.removeChild(target);
          }
          for (var i = 0, ci; (ci = this.children[i]); i++) {
            if (ci === source) {
              this.children.splice(i, 1, target);
              source.parentNode = null;
              target.parentNode = this;
              return target;
            }
          }
        }
      },
      appendChild: function (node) {
        if (this.type == 'root' || (this.type == 'element' && !dtd.$empty[this.tagName])) {
          if (!this.children) {
            this.children = [];
          }
          if (node.parentNode) {
            node.parentNode.removeChild(node);
          }
          for (var i = 0, ci; (ci = this.children[i]); i++) {
            if (ci === node) {
              this.children.splice(i, 1);
              break;
            }
          }
          this.children.push(node);
          node.parentNode = this;
          return node;
        }
      },
      insertBefore: function (target, source) {
        if (this.children) {
          if (target.parentNode) {
            target.parentNode.removeChild(target);
          }
          for (var i = 0, ci; (ci = this.children[i]); i++) {
            if (ci === source) {
              this.children.splice(i, 0, target);
              target.parentNode = this;
              return target;
            }
          }
        }
      },
      insertAfter: function (target, source) {
        if (this.children) {
          if (target.parentNode) {
            target.parentNode.removeChild(target);
          }
          for (var i = 0, ci; (ci = this.children[i]); i++) {
            if (ci === source) {
              this.children.splice(i + 1, 0, target);
              target.parentNode = this;
              return target;
            }
          }
        }
      },
      removeChild: function (node, keepChildren) {
        if (this.children) {
          for (var i = 0, ci; (ci = this.children[i]); i++) {
            if (ci === node) {
              this.children.splice(i, 1);
              ci.parentNode = null;
              if (keepChildren && ci.children && ci.children.length) {
                for (var j = 0, cj; (cj = ci.children[j]); j++) {
                  this.children.splice(i + j, 0, cj);
                  cj.parentNode = this;
                }
              }
              return ci;
            }
          }
        }
      },
      getAttr: function (attrName) {
        return this.attrs && this.attrs[attrName.toLowerCase()];
      },
      setAttr: function (attrName, attrVal) {
        if (!attrName) {
          delete this.attrs;
          return;
        }
        if (!this.attrs) {
          this.attrs = {};
        }
        if (utils.isObject(attrName)) {
          for (var a in attrName) {
            if (!attrName[a]) {
              delete this.attrs[a];
            } else {
              this.attrs[a.toLowerCase()] = attrName[a];
            }
          }
        } else {
          if (!attrVal) {
            delete this.attrs[attrName];
          } else {
            this.attrs[attrName.toLowerCase()] = attrVal;
          }
        }
      },
      getIndex: function () {
        var parent = this.parentNode;
        for (var i = 0, ci; (ci = parent.children[i]); i++) {
          if (ci === this) {
            return i;
          }
        }
        return -1;
      },
      getNodeById: function (id) {
        var node;
        if (this.children && this.children.length) {
          for (var i = 0, ci; (ci = this.children[i++]); ) {
            if ((node = getNodeById(ci, id))) {
              return node;
            }
          }
        }
      },
      getNodesByTagName: function (tagNames) {
        tagNames = utils
          .trim(tagNames)
          .replace(/[ ]{2,}/g, ' ')
          .split(' ');
        var arr = [],
          me = this;
        utils.each(tagNames, function (tagName) {
          if (me.children && me.children.length) {
            for (var i = 0, ci; (ci = me.children[i++]); ) {
              getNodesByTagName(ci, tagName, arr);
            }
          }
        });
        return arr;
      },
      getStyle: function (name) {
        var cssStyle = this.getAttr('style');
        if (!cssStyle) {
          return '';
        }
        var reg = new RegExp('(^|;)\\s*' + name + ':([^;]+)', 'i');
        var match = cssStyle.match(reg);
        if (match && match[0]) {
          return match[2];
        }
        return '';
      },
      setStyle: function (name, val) {
        function exec(name, val) {
          var reg = new RegExp('(^|;)\\s*' + name + ':([^;]+;?)', 'gi');
          cssStyle = cssStyle.replace(reg, '$1');
          if (val) {
            cssStyle = name + ':' + utils.unhtml(val) + ';' + cssStyle;
          }
        }
        var cssStyle = this.getAttr('style');
        if (!cssStyle) {
          cssStyle = '';
        }
        if (utils.isObject(name)) {
          for (var a in name) {
            exec(a, name[a]);
          }
        } else {
          exec(name, val);
        }
        this.setAttr('style', utils.trim(cssStyle));
      },
      traversal: function (fn) {
        if (this.children && this.children.length) {
          nodeTraversal(this, fn);
        }
        return this;
      },
    };
  })();
  var htmlparser = (UE.htmlparser = function (htmlstr, ignoreBlank) {
    var re_tag =
        /<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)-->)|(?:([^\/\s>]+)((?:\s+[\w\-:.]+(?:\s*=\s*?(?:(?:"[^"]*")|(?:'[^']*')|[^\s"'\/>]+))?)*)[\S\s]*?(\/?)>))/g,
      re_attr = /([\w\-:.]+)(?:(?:\s*=\s*(?:(?:"([^"]*)")|(?:'([^']*)')|([^\s>]+)))|(?=\s|$))/g;
    var allowEmptyTags = {
      b: 1,
      code: 1,
      i: 1,
      u: 1,
      strike: 1,
      s: 1,
      tt: 1,
      strong: 1,
      q: 1,
      samp: 1,
      em: 1,
      span: 1,
      sub: 1,
      img: 1,
      sup: 1,
      font: 1,
      big: 1,
      small: 1,
      iframe: 1,
      a: 1,
      br: 1,
      pre: 1,
    };
    htmlstr = htmlstr.replace(new RegExp(domUtils.fillChar, 'g'), '');
    if (!ignoreBlank) {
      htmlstr = htmlstr.replace(
        new RegExp(
          '[\\r\\t\\n' +
            (ignoreBlank ? '' : ' ') +
            ']*</?(\\w+)\\s*(?:[^>]*)>[\\r\\t\\n' +
            (ignoreBlank ? '' : ' ') +
            ']*',
          'g',
        ),
        function (a, b) {
          if (b && allowEmptyTags[b.toLowerCase()]) {
            return a.replace(/(^[\n\r]+)|([\n\r]+$)/g, '');
          }
          return a
            .replace(new RegExp('^[\\r\\n' + (ignoreBlank ? '' : ' ') + ']+'), '')
            .replace(new RegExp('[\\r\\n' + (ignoreBlank ? '' : ' ') + ']+$'), '');
        },
      );
    }
    var notTransAttrs = { href: 1, src: 1 };
    var uNode = UE.uNode,
      needParentNode = {
        td: 'tr',
        tr: ['tbody', 'thead', 'tfoot'],
        tbody: 'table',
        th: 'tr',
        thead: 'table',
        tfoot: 'table',
        caption: 'table',
        li: ['ul', 'ol'],
        dt: 'dl',
        dd: 'dl',
        option: 'select',
      },
      needChild = { ol: 'li', ul: 'li' };
    function text(parent, data) {
      if (needChild[parent.tagName]) {
        var tmpNode = uNode.createElement(needChild[parent.tagName]);
        parent.appendChild(tmpNode);
        tmpNode.appendChild(uNode.createText(data));
        parent = tmpNode;
      } else {
        parent.appendChild(uNode.createText(data));
      }
    }
    function element(parent, tagName, htmlattr) {
      var needParentTag;
      if ((needParentTag = needParentNode[tagName])) {
        var tmpParent = parent,
          hasParent;
        while (tmpParent.type != 'root') {
          if (
            utils.isArray(needParentTag)
              ? utils.indexOf(needParentTag, tmpParent.tagName) != -1
              : needParentTag == tmpParent.tagName
          ) {
            parent = tmpParent;
            hasParent = true;
            break;
          }
          tmpParent = tmpParent.parentNode;
        }
        if (!hasParent) {
          parent = element(parent, utils.isArray(needParentTag) ? needParentTag[0] : needParentTag);
        }
      }
      var elm = new uNode({
        parentNode: parent,
        type: 'element',
        tagName: tagName.toLowerCase(),
        children: dtd.$empty[tagName] ? null : [],
      });
      if (htmlattr) {
        var attrs = {},
          match;
        while ((match = re_attr.exec(htmlattr))) {
          attrs[match[1].toLowerCase()] = notTransAttrs[match[1].toLowerCase()]
            ? match[2] || match[3] || match[4]
            : utils.unhtml(match[2] || match[3] || match[4]);
        }
        elm.attrs = attrs;
      }
      parent.children.push(elm);
      return dtd.$empty[tagName] ? parent : elm;
    }
    function comment(parent, data) {
      parent.children.push(new uNode({ type: 'comment', data: data, parentNode: parent }));
    }
    var match,
      currentIndex = 0,
      nextIndex = 0;
    var root = new uNode({ type: 'root', children: [] });
    var currentParent = root;
    while ((match = re_tag.exec(htmlstr))) {
      currentIndex = match.index;
      try {
        if (currentIndex > nextIndex) {
          text(currentParent, htmlstr.slice(nextIndex, currentIndex));
        }
        if (match[3]) {
          if (dtd.$cdata[currentParent.tagName]) {
            text(currentParent, match[0]);
          } else {
            currentParent = element(currentParent, match[3].toLowerCase(), match[4]);
          }
        } else if (match[1]) {
          if (currentParent.type != 'root') {
            if (dtd.$cdata[currentParent.tagName] && !dtd.$cdata[match[1]]) {
              text(currentParent, match[0]);
            } else {
              var tmpParent = currentParent;
              while (currentParent.type == 'element' && currentParent.tagName != match[1].toLowerCase()) {
                currentParent = currentParent.parentNode;
                if (currentParent.type == 'root') {
                  currentParent = tmpParent;
                  throw 'break';
                }
              }
              currentParent = currentParent.parentNode;
            }
          }
        } else if (match[2]) {
          comment(currentParent, match[2]);
        }
      } catch (e) {}
      nextIndex = re_tag.lastIndex;
    }
    if (nextIndex < htmlstr.length) {
      text(currentParent, htmlstr.slice(nextIndex));
    }
    return root;
  });
  var filterNode = (UE.filterNode = (function () {
    function filterNode(node, rules) {
      switch (node.type) {
        case 'text':
          break;
        case 'element':
          var val;
          if ((val = rules[node.tagName])) {
            if (val === '-') {
              node.parentNode.removeChild(node);
            } else if (utils.isFunction(val)) {
              var parentNode = node.parentNode,
                index = node.getIndex();
              val(node);
              if (node.parentNode) {
                if (node.children) {
                  for (var i = 0, ci; (ci = node.children[i]); ) {
                    filterNode(ci, rules);
                    if (ci.parentNode) {
                      i++;
                    }
                  }
                }
              } else {
                for (var i = index, ci; (ci = parentNode.children[i]); ) {
                  filterNode(ci, rules);
                  if (ci.parentNode) {
                    i++;
                  }
                }
              }
            } else {
              var attrs = val['$'];
              if (attrs && node.attrs) {
                var tmpAttrs = {},
                  tmpVal;
                for (var a in attrs) {
                  tmpVal = node.getAttr(a);
                  if (a == 'style' && utils.isArray(attrs[a])) {
                    var tmpCssStyle = [];
                    utils.each(attrs[a], function (v) {
                      var tmp;
                      if ((tmp = node.getStyle(v))) {
                        tmpCssStyle.push(v + ':' + tmp);
                      }
                    });
                    tmpVal = tmpCssStyle.join(';');
                  }
                  if (tmpVal) {
                    tmpAttrs[a] = tmpVal;
                  }
                }
                node.attrs = tmpAttrs;
              }
              if (node.children) {
                for (var i = 0, ci; (ci = node.children[i]); ) {
                  filterNode(ci, rules);
                  if (ci.parentNode) {
                    i++;
                  }
                }
              }
            }
          } else {
            if (dtd.$cdata[node.tagName]) {
              node.parentNode.removeChild(node);
            } else {
              var parentNode = node.parentNode,
                index = node.getIndex();
              node.parentNode.removeChild(node, true);
              for (var i = index, ci; (ci = parentNode.children[i]); ) {
                filterNode(ci, rules);
                if (ci.parentNode) {
                  i++;
                }
              }
            }
          }
          break;
        case 'comment':
          node.parentNode.removeChild(node);
      }
    }
    return function (root, rules) {
      if (utils.isEmptyObject(rules)) {
        return root;
      }
      var val;
      if ((val = rules['-'])) {
        utils.each(val.split(' '), function (k) {
          rules[k] = '-';
        });
      }
      for (var i = 0, ci; (ci = root.children[i]); ) {
        filterNode(ci, rules);
        if (ci.parentNode) {
          i++;
        }
      }
      return root;
    };
  })());
  UE.plugin = (function () {
    var _plugins = {};
    return {
      register: function (pluginName, fn, oldOptionName, afterDisabled) {
        if (oldOptionName && utils.isFunction(oldOptionName)) {
          afterDisabled = oldOptionName;
          oldOptionName = null;
        }
        _plugins[pluginName] = { optionName: oldOptionName || pluginName, execFn: fn, afterDisabled: afterDisabled };
      },
      load: function (editor) {
        utils.each(_plugins, function (plugin) {
          var _export = plugin.execFn.call(editor);
          if (editor.options[plugin.optionName] !== false) {
            if (_export) {
              utils.each(_export, function (v, k) {
                switch (k.toLowerCase()) {
                  case 'shortcutkey':
                    editor.addshortcutkey(v);
                    break;
                  case 'bindevents':
                    utils.each(v, function (fn, eventName) {
                      editor.addListener(eventName, fn);
                    });
                    break;
                  case 'bindmultievents':
                    utils.each(utils.isArray(v) ? v : [v], function (event) {
                      var types = utils.trim(event.type).split(/\s+/);
                      utils.each(types, function (eventName) {
                        editor.addListener(eventName, event.handler);
                      });
                    });
                    break;
                  case 'commands':
                    utils.each(v, function (execFn, execName) {
                      editor.commands[execName] = execFn;
                    });
                    break;
                  case 'outputrule':
                    editor.addOutputRule(v);
                    break;
                  case 'inputrule':
                    editor.addInputRule(v);
                    break;
                  case 'defaultoptions':
                    editor.setOpt(v);
                }
              });
            }
          } else if (plugin.afterDisabled) {
            plugin.afterDisabled.call(editor);
          }
        });
        utils.each(UE.plugins, function (plugin) {
          plugin.call(editor);
        });
      },
      run: function (pluginName, editor) {
        var plugin = _plugins[pluginName];
        if (plugin) {
          plugin.exeFn.call(editor);
        }
      },
    };
  })();
  var keymap = (UE.keymap = {
    Backspace: 8,
    Tab: 9,
    Enter: 13,
    Shift: 16,
    Control: 17,
    Alt: 18,
    CapsLock: 20,
    Esc: 27,
    Spacebar: 32,
    PageUp: 33,
    PageDown: 34,
    End: 35,
    Home: 36,
    Left: 37,
    Up: 38,
    Right: 39,
    Down: 40,
    Insert: 45,
    Del: 46,
    NumLock: 144,
    Cmd: 91,
    '=': 187,
    '-': 189,
    b: 66,
    i: 73,
    z: 90,
    y: 89,
    v: 86,
    x: 88,
    s: 83,
    n: 78,
  });
  var LocalStorage = (UE.LocalStorage = (function () {
    var storage = window.localStorage;
    return {
      saveLocalData: function (key, data) {
        if (!storage) {
          return false;
        }
        storage.setItem(key, data);
        return true;
      },
      getLocalData: function (key) {
        if (!storage) {
          return null;
        }
        return storage.getItem(key) || null;
      },
      removeItem: function (key) {
        storage && storage.removeItem(key);
      },
    };
  })());
  (function () {
    var ROOT_KEY = 'UEditorPlusPref';
    UE.Editor.prototype.setPreferences = function (key, value) {
      var obj = {};
      if (utils.isString(key)) {
        obj[key] = value;
      } else {
        obj = key;
      }
      var data = LocalStorage.getLocalData(ROOT_KEY);
      if (data && (data = utils.str2json(data))) {
        utils.extend(data, obj);
      } else {
        data = obj;
      }
      data && LocalStorage.saveLocalData(ROOT_KEY, utils.json2str(data));
    };
    UE.Editor.prototype.getPreferences = function (key) {
      var data = LocalStorage.getLocalData(ROOT_KEY);
      if (data && (data = utils.str2json(data))) {
        return key ? data[key] : data;
      }
      return null;
    };
    UE.Editor.prototype.removePreferences = function (key) {
      var data = LocalStorage.getLocalData(ROOT_KEY);
      if (data && (data = utils.str2json(data))) {
        data[key] = undefined;
        delete data[key];
      }
      data && LocalStorage.saveLocalData(ROOT_KEY, utils.json2str(data));
    };
  })();
  UE.plugins['defaultfilter'] = function () {
    var me = this;
    me.setOpt({ allowDivTransToP: true, disabledTableInTable: true, rgb2Hex: true });
    me.addInputRule(function (root) {
      var allowDivTransToP = this.options.allowDivTransToP;
      var val;
      function tdParent(node) {
        while (node && node.type == 'element') {
          if (node.tagName == 'td') {
            return true;
          }
          node = node.parentNode;
        }
        return false;
      }
      root.traversal(function (node) {
        if (node.type == 'element') {
          if (
            !dtd.$cdata[node.tagName] &&
            me.options.autoClearEmptyNode &&
            dtd.$inline[node.tagName] &&
            !dtd.$empty[node.tagName] &&
            (!node.attrs || utils.isEmptyObject(node.attrs))
          ) {
            if (!node.firstChild()) node.parentNode.removeChild(node);
            else if (node.tagName == 'span' && (!node.attrs || utils.isEmptyObject(node.attrs))) {
              node.parentNode.removeChild(node, true);
            }
            return;
          }
          switch (node.tagName) {
            case 'style':
            case 'script':
              node.setAttr({ cdata_tag: node.tagName, cdata_data: node.innerHTML() || '', _ue_custom_node_: 'true' });
              node.tagName = 'div';
              node.innerHTML('');
              break;
            case 'a':
              if ((val = node.getAttr('href'))) {
                node.setAttr('_href', val);
              }
              break;
            case 'img':
              if ((val = node.getAttr('src'))) {
                if (/^data:/.test(val)) {
                  node.parentNode.removeChild(node);
                  break;
                }
              }
              node.setAttr('_src', node.getAttr('src'));
              break;
            case 'span':
              if (browser.webkit && (val = node.getStyle('white-space'))) {
                if (/nowrap|normal/.test(val)) {
                  node.setStyle('white-space', '');
                  if (me.options.autoClearEmptyNode && utils.isEmptyObject(node.attrs)) {
                    node.parentNode.removeChild(node, true);
                  }
                }
              }
              val = node.getAttr('id');
              if (val && /^_baidu_bookmark_/i.test(val)) {
                node.parentNode.removeChild(node);
              }
              break;
            case 'p':
              if ((val = node.getAttr('align'))) {
                node.setAttr('align');
                node.setStyle('text-align', val);
              }
              utils.each(node.children, function (n) {
                if (n.type == 'element' && n.tagName == 'p') {
                  var next = n.nextSibling();
                  node.parentNode.insertAfter(n, node);
                  var last = n;
                  while (next) {
                    var tmp = next.nextSibling();
                    node.parentNode.insertAfter(next, last);
                    last = next;
                    next = tmp;
                  }
                  return false;
                }
              });
              if (!node.firstChild()) {
                node.innerHTML(browser.ie ? '&nbsp;' : '<br/>');
              }
              break;
            case 'div':
              if (node.getAttr('cdata_tag')) {
                break;
              }
              val = node.getAttr('class');
              if (val && /^line number\d+/.test(val)) {
                break;
              }
              if (!allowDivTransToP) {
                break;
              }
              var tmpNode,
                p = UE.uNode.createElement('p');
              while ((tmpNode = node.firstChild())) {
                if (tmpNode.type == 'text' || !UE.dom.dtd.$block[tmpNode.tagName]) {
                  p.appendChild(tmpNode);
                } else {
                  if (p.firstChild()) {
                    node.parentNode.insertBefore(p, node);
                    p = UE.uNode.createElement('p');
                  } else {
                    node.parentNode.insertBefore(tmpNode, node);
                  }
                }
              }
              if (p.firstChild()) {
                node.parentNode.insertBefore(p, node);
              }
              node.parentNode.removeChild(node);
              break;
            case 'dl':
              node.tagName = 'ul';
              break;
            case 'dt':
            case 'dd':
              node.tagName = 'li';
              break;
            case 'li':
              var className = node.getAttr('class');
              if (!className || !/list\-/.test(className)) {
                node.setAttr();
              }
              var tmpNodes = node.getNodesByTagName('ol ul');
              UE.utils.each(tmpNodes, function (n) {
                node.parentNode.insertAfter(n, node);
              });
              break;
            case 'td':
            case 'th':
            case 'caption':
              if (!node.children || !node.children.length) {
                node.appendChild(browser.ie11below ? UE.uNode.createText(' ') : UE.uNode.createElement('br'));
              }
              break;
            case 'table':
              if (me.options.disabledTableInTable && tdParent(node)) {
                node.parentNode.insertBefore(UE.uNode.createText(node.innerText()), node);
                node.parentNode.removeChild(node);
              }
          }
        }
      });
    });
    me.addOutputRule(function (root) {
      var val;
      root.traversal(function (node) {
        if (node.type == 'element') {
          if (
            me.options.autoClearEmptyNode &&
            dtd.$inline[node.tagName] &&
            !dtd.$empty[node.tagName] &&
            (!node.attrs || utils.isEmptyObject(node.attrs))
          ) {
            if (!node.firstChild()) node.parentNode.removeChild(node);
            else if (node.tagName == 'span' && (!node.attrs || utils.isEmptyObject(node.attrs))) {
              node.parentNode.removeChild(node, true);
            }
            return;
          }
          switch (node.tagName) {
            case 'div':
              if ((val = node.getAttr('cdata_tag'))) {
                node.tagName = val;
                node.appendChild(UE.uNode.createText(node.getAttr('cdata_data')));
                node.setAttr({ cdata_tag: '', cdata_data: '', _ue_custom_node_: '' });
              }
              break;
            case 'a':
              if ((val = node.getAttr('_href'))) {
                node.setAttr({ href: utils.html(val), _href: '' });
              }
              break;
            case 'span':
              val = node.getAttr('id');
              if (val && /^_baidu_bookmark_/i.test(val)) {
                node.parentNode.removeChild(node);
              }
              if (me.getOpt('rgb2Hex')) {
                var cssStyle = node.getAttr('style');
                if (cssStyle) {
                  node.setAttr(
                    'style',
                    cssStyle.replace(/rgba?\(([\d,\s]+)\)/g, function (a, value) {
                      var array = value.split(',');
                      if (array.length > 3) return '';
                      value = '#';
                      for (var i = 0, color; (color = array[i++]); ) {
                        color = parseInt(color.replace(/[^\d]/gi, ''), 10).toString(16);
                        value += color.length == 1 ? '0' + color : color;
                      }
                      return value.toUpperCase();
                    }),
                  );
                }
              }
              break;
            case 'img':
              if ((val = node.getAttr('_src'))) {
                node.setAttr({ src: node.getAttr('_src'), _src: '' });
              }
          }
        }
      });
    });
  };
  UE.commands['inserthtml'] = {
    execCommand: function (command, html, notNeedFilter) {
      var me = this,
        range,
        div;
      if (!html) {
        return;
      }
      if (me.fireEvent('beforeinserthtml', html) === true) {
        return;
      }
      range = me.selection.getRange();
      div = range.document.createElement('div');
      div.style.display = 'inline';
      if (!notNeedFilter) {
        var root = UE.htmlparser(html);
        if (me.options.filterRules) {
          UE.filterNode(root, me.options.filterRules);
        }
        me.filterInputRule(root);
        html = root.toHtml();
      }
      div.innerHTML = utils.trim(html);
      if (!range.collapsed) {
        var tmpNode = range.startContainer;
        if (domUtils.isFillChar(tmpNode)) {
          range.setStartBefore(tmpNode);
        }
        tmpNode = range.endContainer;
        if (domUtils.isFillChar(tmpNode)) {
          range.setEndAfter(tmpNode);
        }
        range.txtToElmBoundary();
        if (range.endContainer && range.endContainer.nodeType == 1) {
          tmpNode = range.endContainer.childNodes[range.endOffset];
          if (tmpNode && domUtils.isBr(tmpNode)) {
            range.setEndAfter(tmpNode);
          }
        }
        if (range.startOffset == 0) {
          tmpNode = range.startContainer;
          if (domUtils.isBoundaryNode(tmpNode, 'firstChild')) {
            tmpNode = range.endContainer;
            if (
              range.endOffset == (tmpNode.nodeType == 3 ? tmpNode.nodeValue.length : tmpNode.childNodes.length) &&
              domUtils.isBoundaryNode(tmpNode, 'lastChild')
            ) {
              me.body.innerHTML = '<p>' + (browser.ie ? '' : '<br/>') + '</p>';
              range.setStart(me.body.firstChild, 0).collapse(true);
            }
          }
        }
        !range.collapsed && range.deleteContents();
        if (range.startContainer.nodeType == 1) {
          var child = range.startContainer.childNodes[range.startOffset],
            pre;
          if (child && domUtils.isBlockElm(child) && (pre = child.previousSibling) && domUtils.isBlockElm(pre)) {
            range.setEnd(pre, pre.childNodes.length).collapse();
            while (child.firstChild) {
              pre.appendChild(child.firstChild);
            }
            domUtils.remove(child);
          }
        }
      }
      var child,
        parent,
        pre,
        tmp,
        hadBreak = 0,
        nextNode;
      if (range.inFillChar()) {
        child = range.startContainer;
        if (domUtils.isFillChar(child)) {
          range.setStartBefore(child).collapse(true);
          domUtils.remove(child);
        } else if (domUtils.isFillChar(child, true)) {
          child.nodeValue = child.nodeValue.replace(fillCharReg, '');
          range.startOffset--;
          range.collapsed && range.collapse(true);
        }
      }
      var li = domUtils.findParentByTagName(range.startContainer, 'li', true);
      if (li) {
        var next, last;
        while ((child = div.firstChild)) {
          while (child && (child.nodeType == 3 || !domUtils.isBlockElm(child) || child.tagName == 'HR')) {
            next = child.nextSibling;
            range.insertNode(child).collapse();
            last = child;
            child = next;
          }
          if (child) {
            if (/^(ol|ul)$/i.test(child.tagName)) {
              while (child.firstChild) {
                last = child.firstChild;
                domUtils.insertAfter(li, child.firstChild);
                li = li.nextSibling;
              }
              domUtils.remove(child);
            } else {
              var tmpLi;
              next = child.nextSibling;
              tmpLi = me.document.createElement('li');
              domUtils.insertAfter(li, tmpLi);
              tmpLi.appendChild(child);
              last = child;
              child = next;
              li = tmpLi;
            }
          }
        }
        li = domUtils.findParentByTagName(range.startContainer, 'li', true);
        if (domUtils.isEmptyBlock(li)) {
          domUtils.remove(li);
        }
        if (last) {
          range.setStartAfter(last).collapse(true).select(true);
        }
      } else {
        while ((child = div.firstChild)) {
          if (hadBreak) {
            var p = me.document.createElement('p');
            while (child && (child.nodeType == 3 || !dtd.$block[child.tagName])) {
              nextNode = child.nextSibling;
              p.appendChild(child);
              child = nextNode;
            }
            if (p.firstChild) {
              child = p;
            }
          }
          range.insertNode(child);
          nextNode = child.nextSibling;
          if (!hadBreak && child.nodeType == domUtils.NODE_ELEMENT && domUtils.isBlockElm(child)) {
            parent = domUtils.findParent(child, function (node) {
              return domUtils.isBlockElm(node);
            });
            if (
              parent &&
              parent.tagName.toLowerCase() != 'body' &&
              !(dtd[parent.tagName][child.nodeName] && child.parentNode === parent)
            ) {
              if (!dtd[parent.tagName][child.nodeName]) {
                pre = parent;
              } else {
                tmp = child.parentNode;
                while (tmp !== parent) {
                  pre = tmp;
                  tmp = tmp.parentNode;
                }
              }
              domUtils.breakParent(child, pre || tmp);
              var pre = child.previousSibling;
              domUtils.trimWhiteTextNode(pre);
              if (!pre.childNodes.length) {
                domUtils.remove(pre);
              }
              if (
                !browser.ie &&
                (next = child.nextSibling) &&
                domUtils.isBlockElm(next) &&
                next.lastChild &&
                !domUtils.isBr(next.lastChild)
              ) {
                next.appendChild(me.document.createElement('br'));
              }
              hadBreak = 1;
            }
          }
          var next = child.nextSibling;
          if (!div.firstChild && next && domUtils.isBlockElm(next)) {
            range.setStart(next, 0).collapse(true);
            break;
          }
          range.setEndAfter(child).collapse();
        }
        child = range.startContainer;
        if (nextNode && domUtils.isBr(nextNode)) {
          domUtils.remove(nextNode);
        }
        if (domUtils.isBlockElm(child) && domUtils.isEmptyNode(child)) {
          if ((nextNode = child.nextSibling)) {
            domUtils.remove(child);
            if (nextNode.nodeType == 1 && dtd.$block[nextNode.tagName]) {
              range.setStart(nextNode, 0).collapse(true).shrinkBoundary();
            }
          } else {
            try {
              child.innerHTML = browser.ie ? domUtils.fillChar : '<br/>';
            } catch (e) {
              range.setStartBefore(child);
              domUtils.remove(child);
            }
          }
        }
        try {
          range.select(true);
        } catch (e) {}
      }
      setTimeout(function () {
        range = me.selection.getRange();
        range.scrollToView(me.autoHeightEnabled, me.autoHeightEnabled ? domUtils.getXY(me.iframe).y : 0);
        me.fireEvent('afterinserthtml', html);
      }, 200);
    },
  };
  UE.plugins['autotypeset'] = function () {
    this.setOpt({
      autotypeset: {
        mergeEmptyline: true,
        removeClass: true,
        removeEmptyline: false,
        textAlign: 'left',
        imageBlockLine: 'center',
        pasteFilter: false,
        clearFontSize: false,
        clearFontFamily: false,
        removeEmptyNode: false,
        removeTagNames: utils.extend({ div: 1 }, dtd.$removeEmpty),
        indent: false,
        indentValue: '2em',
        bdc2sb: false,
        tobdc: false,
      },
    });
    var me = this,
      opt = me.options.autotypeset,
      remainClass = { selectTdClass: 1, pagebreak: 1, anchorclass: 1 },
      remainTag = { li: 1 },
      tags = { div: 1, p: 1, blockquote: 1, center: 1, h1: 1, h2: 1, h3: 1, h4: 1, h5: 1, h6: 1, span: 1 },
      highlightCont;
    if (!opt) {
      return;
    }
    readLocalOpts();
    function isLine(node, notEmpty) {
      if (!node || node.nodeType == 3) return 0;
      if (domUtils.isBr(node)) return 1;
      if (node && node.parentNode && tags[node.tagName.toLowerCase()]) {
        if ((highlightCont && highlightCont.contains(node)) || node.getAttribute('pagebreak')) {
          return 0;
        }
        return notEmpty
          ? !domUtils.isEmptyBlock(node)
          : domUtils.isEmptyBlock(node, new RegExp('[\\s' + domUtils.fillChar + ']', 'g'));
      }
    }
    function removeNotAttributeSpan(node) {
      if (!node.style.cssText) {
        domUtils.removeAttributes(node, ['style']);
        if (node.tagName.toLowerCase() == 'span' && domUtils.hasNoAttributes(node)) {
          domUtils.remove(node, true);
        }
      }
    }
    function autotype(type, html) {
      var me = this,
        cont;
      if (html) {
        if (!opt.pasteFilter) {
          return;
        }
        cont = me.document.createElement('div');
        cont.innerHTML = html.html;
      } else {
        cont = me.document.body;
      }
      var nodes = domUtils.getElementsByTagName(cont, '*');
      for (var i = 0, ci; (ci = nodes[i++]); ) {
        if (me.fireEvent('excludeNodeinautotype', ci) === true) {
          continue;
        }
        if (opt.clearFontSize && ci.style.fontSize) {
          domUtils.removeStyle(ci, 'font-size');
          removeNotAttributeSpan(ci);
        }
        if (opt.clearFontFamily && ci.style.fontFamily) {
          domUtils.removeStyle(ci, 'font-family');
          removeNotAttributeSpan(ci);
        }
        if (isLine(ci)) {
          if (opt.mergeEmptyline) {
            var next = ci.nextSibling,
              tmpNode,
              isBr = domUtils.isBr(ci);
            while (isLine(next)) {
              tmpNode = next;
              next = tmpNode.nextSibling;
              if (isBr && (!next || (next && !domUtils.isBr(next)))) {
                break;
              }
              domUtils.remove(tmpNode);
            }
          }
          if (opt.removeEmptyline && domUtils.inDoc(ci, cont) && !remainTag[ci.parentNode.tagName.toLowerCase()]) {
            if (domUtils.isBr(ci)) {
              next = ci.nextSibling;
              if (next && !domUtils.isBr(next)) {
                continue;
              }
            }
            domUtils.remove(ci);
            continue;
          }
        }
        if (isLine(ci, true) && ci.tagName != 'SPAN') {
          if (opt.indent) {
            ci.style.textIndent = opt.indentValue;
          }
          if (opt.textAlign) {
            ci.style.textAlign = opt.textAlign;
          }
        }
        if (opt.removeClass && ci.className && !remainClass[ci.className.toLowerCase()]) {
          if (highlightCont && highlightCont.contains(ci)) {
            continue;
          }
          domUtils.removeAttributes(ci, ['class']);
        }
        if (opt.imageBlockLine && ci.tagName.toLowerCase() == 'img' && !ci.getAttribute('emotion')) {
          if (html) {
            var img = ci;
            switch (opt.imageBlockLine) {
              case 'left':
              case 'right':
              case 'none':
                var pN = img.parentNode,
                  tmpNode,
                  pre,
                  next;
                while (dtd.$inline[pN.tagName] || pN.tagName == 'A') {
                  pN = pN.parentNode;
                }
                tmpNode = pN;
                if (tmpNode.tagName == 'P' && domUtils.getStyle(tmpNode, 'text-align') == 'center') {
                  if (
                    !domUtils.isBody(tmpNode) &&
                    domUtils.getChildCount(tmpNode, function (node) {
                      return !domUtils.isBr(node) && !domUtils.isWhitespace(node);
                    }) == 1
                  ) {
                    pre = tmpNode.previousSibling;
                    next = tmpNode.nextSibling;
                    if (
                      pre &&
                      next &&
                      pre.nodeType == 1 &&
                      next.nodeType == 1 &&
                      pre.tagName == next.tagName &&
                      domUtils.isBlockElm(pre)
                    ) {
                      pre.appendChild(tmpNode.firstChild);
                      while (next.firstChild) {
                        pre.appendChild(next.firstChild);
                      }
                      domUtils.remove(tmpNode);
                      domUtils.remove(next);
                    } else {
                      domUtils.setStyle(tmpNode, 'text-align', '');
                    }
                  }
                }
                domUtils.setStyle(img, 'float', opt.imageBlockLine);
                break;
              case 'center':
                if (me.queryCommandValue('imagefloat') != 'center') {
                  pN = img.parentNode;
                  domUtils.setStyle(img, 'float', 'none');
                  tmpNode = img;
                  while (
                    pN &&
                    domUtils.getChildCount(pN, function (node) {
                      return !domUtils.isBr(node) && !domUtils.isWhitespace(node);
                    }) == 1 &&
                    (dtd.$inline[pN.tagName] || pN.tagName == 'A')
                  ) {
                    tmpNode = pN;
                    pN = pN.parentNode;
                  }
                  var pNode = me.document.createElement('p');
                  domUtils.setAttributes(pNode, { style: 'text-align:center' });
                  tmpNode.parentNode.insertBefore(pNode, tmpNode);
                  pNode.appendChild(tmpNode);
                  domUtils.setStyle(tmpNode, 'float', '');
                }
            }
          } else {
            var range = me.selection.getRange();
            range.selectNode(ci).select();
            me.execCommand('imagefloat', opt.imageBlockLine);
          }
        }
        if (opt.removeEmptyNode) {
          if (
            opt.removeTagNames[ci.tagName.toLowerCase()] &&
            domUtils.hasNoAttributes(ci) &&
            domUtils.isEmptyBlock(ci)
          ) {
            domUtils.remove(ci);
          }
        }
      }
      if (opt.tobdc) {
        var root = UE.htmlparser(cont.innerHTML);
        root.traversal(function (node) {
          if (node.type == 'text') {
            node.data = ToDBC(node.data);
          }
        });
        cont.innerHTML = root.toHtml();
      }
      if (opt.bdc2sb) {
        var root = UE.htmlparser(cont.innerHTML);
        root.traversal(function (node) {
          if (node.type == 'text') {
            node.data = DBC2SB(node.data);
          }
        });
        cont.innerHTML = root.toHtml();
      }
      if (html) {
        html.html = cont.innerHTML;
      }
    }
    if (opt.pasteFilter) {
      me.addListener('beforepaste', autotype);
    }
    function DBC2SB(str) {
      var result = '';
      for (var i = 0; i < str.length; i++) {
        var code = str.charCodeAt(i);
        if (code >= 65281 && code <= 65373) {
          result += String.fromCharCode(str.charCodeAt(i) - 65248);
        } else if (code == 12288) {
          result += String.fromCharCode(str.charCodeAt(i) - 12288 + 32);
        } else {
          result += str.charAt(i);
        }
      }
      return result;
    }
    function ToDBC(txtstring) {
      txtstring = utils.html(txtstring);
      var tmp = '';
      var mark = '';
      for (var i = 0; i < txtstring.length; i++) {
        if (txtstring.charCodeAt(i) == 32) {
          tmp = tmp + String.fromCharCode(12288);
        } else if (txtstring.charCodeAt(i) < 127) {
          tmp = tmp + String.fromCharCode(txtstring.charCodeAt(i) + 65248);
        } else {
          tmp += txtstring.charAt(i);
        }
      }
      return tmp;
    }
    function readLocalOpts() {
      var cookieOpt = me.getPreferences('autotypeset');
      utils.extend(me.options.autotypeset, cookieOpt);
    }
    me.commands['autotypeset'] = {
      execCommand: function () {
        me.removeListener('beforepaste', autotype);
        if (opt.pasteFilter) {
          me.addListener('beforepaste', autotype);
        }
        autotype.call(me);
      },
    };
  };
  UE.plugin.register('autosubmit', function () {
    return {
      shortcutkey: { autosubmit: 'ctrl+13' },
      commands: {
        autosubmit: {
          execCommand: function () {
            var me = this,
              form = domUtils.findParentByTagName(me.iframe, 'form', false);
            if (form) {
              if (me.fireEvent('beforesubmit') === false) {
                return;
              }
              me.sync();
              form.submit();
            }
          },
        },
      },
    };
  });
  UE.plugin.register('background', function () {
    var me = this,
      cssRuleId = 'editor_background',
      isSetColored,
      reg = new RegExp('body[\\s]*\\{(.+)\\}', 'i');
    function stringToObj(str) {
      var obj = {},
        styles = str.split(';');
      utils.each(styles, function (v) {
        var index = v.indexOf(':'),
          key = utils.trim(v.substr(0, index)).toLowerCase();
        key && (obj[key] = utils.trim(v.substr(index + 1) || ''));
      });
      return obj;
    }
    function setBackground(obj) {
      if (obj) {
        var styles = [];
        for (var name in obj) {
          if (obj.hasOwnProperty(name)) {
            styles.push(name + ':' + obj[name] + '; ');
          }
        }
        utils.cssRule(cssRuleId, styles.length ? 'body{' + styles.join('') + '}' : '', me.document);
      } else {
        utils.cssRule(cssRuleId, '', me.document);
      }
    }
    var orgFn = me.hasContents;
    me.hasContents = function () {
      if (me.queryCommandValue('background')) {
        return true;
      }
      return orgFn.apply(me, arguments);
    };
    return {
      bindEvents: {
        getAllHtml: function (type, headHtml) {
          var body = this.body,
            su = domUtils.getComputedStyle(body, 'background-image'),
            url = '';
          if (su.indexOf(me.options.imagePath) > 0) {
            url = su.substring(su.indexOf(me.options.imagePath), su.length - 1).replace(/"|\(|\)/gi, '');
          } else {
            url = su != 'none' ? su.replace(/url\("?|"?\)/gi, '') : '';
          }
          var html = '<style type="text/css">body{';
          var bgObj = {
            'background-color': domUtils.getComputedStyle(body, 'background-color') || '#ffffff',
            'background-image': url ? 'url(' + url + ')' : '',
            'background-repeat': domUtils.getComputedStyle(body, 'background-repeat') || '',
            'background-position': browser.ie
              ? domUtils.getComputedStyle(body, 'background-position-x') +
                ' ' +
                domUtils.getComputedStyle(body, 'background-position-y')
              : domUtils.getComputedStyle(body, 'background-position'),
            height: domUtils.getComputedStyle(body, 'height'),
          };
          for (var name in bgObj) {
            if (bgObj.hasOwnProperty(name)) {
              html += name + ':' + bgObj[name] + '; ';
            }
          }
          html += '}</style> ';
          headHtml.push(html);
        },
        aftersetcontent: function () {
          if (isSetColored == false) setBackground();
        },
      },
      inputRule: function (root) {
        isSetColored = false;
        utils.each(root.getNodesByTagName('p'), function (p) {
          var styles = p.getAttr('data-background');
          if (styles) {
            isSetColored = true;
            setBackground(stringToObj(styles));
            p.parentNode.removeChild(p);
          }
        });
      },
      outputRule: function (root) {
        var me = this,
          styles = (utils.cssRule(cssRuleId, me.document) || '').replace(/[\n\r]+/g, '').match(reg);
        if (styles) {
          root.appendChild(
            UE.uNode.createElement(
              '<p style="display:none;" data-background="' +
                utils.trim(styles[1].replace(/"/g, '').replace(/[\s]+/g, ' ')) +
                '"><br/></p>',
            ),
          );
        }
      },
      commands: {
        background: {
          execCommand: function (cmd, obj) {
            setBackground(obj);
          },
          queryCommandValue: function () {
            var me = this,
              styles = (utils.cssRule(cssRuleId, me.document) || '').replace(/[\n\r]+/g, '').match(reg);
            return styles ? stringToObj(styles[1]) : null;
          },
          notNeedUndo: true,
        },
      },
    };
  });
  UE.commands['imagefloat'] = {
    execCommand: function (cmd, align) {
      var me = this,
        range = me.selection.getRange();
      if (!range.collapsed) {
        var img = range.getClosedNode();
        if (img && img.tagName === 'IMG') {
          switch (align) {
            case 'left':
            case 'right':
            case 'none':
              var pN = img.parentNode,
                tmpNode,
                pre,
                next;
              while (dtd.$inline[pN.tagName] || pN.tagName == 'A') {
                pN = pN.parentNode;
              }
              tmpNode = pN;
              if (tmpNode.tagName == 'P' && domUtils.getStyle(tmpNode, 'text-align') == 'center') {
                if (
                  !domUtils.isBody(tmpNode) &&
                  domUtils.getChildCount(tmpNode, function (node) {
                    return !domUtils.isBr(node) && !domUtils.isWhitespace(node);
                  }) == 1
                ) {
                  pre = tmpNode.previousSibling;
                  next = tmpNode.nextSibling;
                  if (
                    pre &&
                    next &&
                    pre.nodeType == 1 &&
                    next.nodeType == 1 &&
                    pre.tagName == next.tagName &&
                    domUtils.isBlockElm(pre)
                  ) {
                    pre.appendChild(tmpNode.firstChild);
                    while (next.firstChild) {
                      pre.appendChild(next.firstChild);
                    }
                    domUtils.remove(tmpNode);
                    domUtils.remove(next);
                  } else {
                    domUtils.setStyle(tmpNode, 'text-align', '');
                  }
                }
                range.selectNode(img).select();
              }
              domUtils.setStyle(img, 'float', align == 'none' ? '' : align);
              if (align == 'none') {
                domUtils.removeAttributes(img, 'align');
              }
              break;
            case 'center':
              if (me.queryCommandValue('imagefloat') != 'center') {
                pN = img.parentNode;
                domUtils.setStyle(img, 'float', '');
                domUtils.removeAttributes(img, 'align');
                tmpNode = img;
                while (
                  pN &&
                  domUtils.getChildCount(pN, function (node) {
                    return !domUtils.isBr(node) && !domUtils.isWhitespace(node);
                  }) == 1 &&
                  (dtd.$inline[pN.tagName] || pN.tagName == 'A')
                ) {
                  tmpNode = pN;
                  pN = pN.parentNode;
                }
                range.setStartBefore(tmpNode).setCursor(false);
                pN = me.document.createElement('div');
                pN.appendChild(tmpNode);
                domUtils.setStyle(tmpNode, 'float', '');
                me.execCommand(
                  'insertHtml',
                  '<p id="_img_parent_tmp" style="text-align:center">' + pN.innerHTML + '</p>',
                );
                tmpNode = me.document.getElementById('_img_parent_tmp');
                tmpNode.removeAttribute('id');
                tmpNode = tmpNode.firstChild;
                range.selectNode(tmpNode).select();
                next = tmpNode.parentNode.nextSibling;
                if (next && domUtils.isEmptyNode(next)) {
                  domUtils.remove(next);
                }
              }
              break;
          }
        }
      }
    },
    queryCommandValue: function () {
      var range = this.selection.getRange(),
        startNode,
        floatStyle;
      if (range.collapsed) {
        return 'none';
      }
      startNode = range.getClosedNode();
      if (startNode && startNode.nodeType == 1 && startNode.tagName == 'IMG') {
        floatStyle = domUtils.getComputedStyle(startNode, 'float') || startNode.getAttribute('align');
        if (floatStyle == 'none') {
          floatStyle =
            domUtils.getComputedStyle(startNode.parentNode, 'text-align') == 'center' ? 'center' : floatStyle;
        }
        return { left: 1, right: 1, center: 1 }[floatStyle] ? floatStyle : 'none';
      }
      return 'none';
    },
    queryCommandState: function () {
      var range = this.selection.getRange(),
        startNode;
      if (range.collapsed) return -1;
      startNode = range.getClosedNode();
      if (startNode && startNode.nodeType === 1 && startNode.tagName === 'IMG') {
        return 0;
      }
      return -1;
    },
  };
  UE.commands['insertimage'] = {
    execCommand: function (cmd, opt) {
      opt = utils.isArray(opt) ? opt : [opt];
      if (!opt.length) {
        return;
      }
      var me = this,
        range = me.selection.getRange(),
        img = range.getClosedNode();
      if (me.fireEvent('beforeinsertimage', opt) === true) {
        return;
      }
      if (
        img &&
        /img/i.test(img.tagName) &&
        (img.className != 'edui-faked-video' || img.className.indexOf('edui-upload-video') != -1) &&
        !img.getAttribute('data-word-image')
      ) {
        var first = opt.shift();
        var floatStyle = first['floatStyle'];
        delete first['floatStyle'];
        domUtils.setAttributes(img, first);
        me.execCommand('imagefloat', floatStyle);
        if (opt.length > 0) {
          range.setStartAfter(img).setCursor(false, true);
          me.execCommand('insertimage', opt);
        }
      } else {
        var html = [],
          str = '',
          ci;
        ci = opt[0];
        if (opt.length == 1) {
          str =
            '<img src="' +
            ci.src +
            '" ' +
            (ci._src ? ' _src="' + ci._src + '" ' : '') +
            (ci.width ? 'width="' + ci.width + '" ' : '') +
            (ci.height ? ' height="' + ci.height + '" ' : '') +
            (ci['floatStyle'] == 'left' || ci['floatStyle'] == 'right'
              ? ' style="float:' + ci['floatStyle'] + ';"'
              : '') +
            (ci.title && ci.title != '' ? ' title="' + ci.title + '"' : '') +
            (ci.border && ci.border != '0' ? ' border="' + ci.border + '"' : '') +
            (ci.alt && ci.alt != '' ? ' alt="' + ci.alt + '"' : '') +
            (ci.hspace && ci.hspace != '0' ? ' hspace = "' + ci.hspace + '"' : '') +
            (ci.vspace && ci.vspace != '0' ? ' vspace = "' + ci.vspace + '"' : '') +
            '/>';
          if (ci['floatStyle'] == 'center') {
            str = '<p style="text-align: center">' + str + '</p>';
          }
          html.push(str);
        } else {
          for (var i = 0; (ci = opt[i++]); ) {
            str =
              '<p ' +
              (ci['floatStyle'] == 'center' ? 'style="text-align: center" ' : '') +
              '><img src="' +
              ci.src +
              '" ' +
              (ci.width ? 'width="' + ci.width + '" ' : '') +
              (ci._src ? ' _src="' + ci._src + '" ' : '') +
              (ci.height ? ' height="' + ci.height + '" ' : '') +
              ' style="' +
              (ci['floatStyle'] && ci['floatStyle'] != 'center' ? 'float:' + ci['floatStyle'] + ';' : '') +
              (ci.border || '') +
              '" ' +
              (ci.title ? ' title="' + ci.title + '"' : '') +
              ' /></p>';
            html.push(str);
          }
        }
        me.execCommand('insertHtml', html.join(''));
      }
      me.fireEvent('afterinsertimage', opt);
    },
  };
  UE.plugins['justify'] = function () {
    var me = this,
      block = domUtils.isBlockElm,
      defaultValue = { left: 1, right: 1, center: 1, justify: 1 },
      doJustify = function (range, style) {
        var bookmark = range.createBookmark(),
          filterFn = function (node) {
            return node.nodeType == 1
              ? node.tagName.toLowerCase() != 'br' && !domUtils.isBookmarkNode(node)
              : !domUtils.isWhitespace(node);
          };
        range.enlarge(true);
        var bookmark2 = range.createBookmark(),
          current = domUtils.getNextDomNode(bookmark2.start, false, filterFn),
          tmpRange = range.cloneRange(),
          tmpNode;
        while (current && !(domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)) {
          if (current.nodeType == 3 || !block(current)) {
            tmpRange.setStartBefore(current);
            while (current && current !== bookmark2.end && !block(current)) {
              tmpNode = current;
              current = domUtils.getNextDomNode(current, false, null, function (node) {
                return !block(node);
              });
            }
            tmpRange.setEndAfter(tmpNode);
            var common = tmpRange.getCommonAncestor();
            if (!domUtils.isBody(common) && block(common)) {
              domUtils.setStyles(common, utils.isString(style) ? { 'text-align': style } : style);
              current = common;
            } else {
              var p = range.document.createElement('p');
              domUtils.setStyles(p, utils.isString(style) ? { 'text-align': style } : style);
              var frag = tmpRange.extractContents();
              p.appendChild(frag);
              tmpRange.insertNode(p);
              current = p;
            }
            current = domUtils.getNextDomNode(current, false, filterFn);
          } else {
            current = domUtils.getNextDomNode(current, true, filterFn);
          }
        }
        return range.moveToBookmark(bookmark2).moveToBookmark(bookmark);
      };
    UE.commands['justify'] = {
      execCommand: function (cmdName, align) {
        var range = this.selection.getRange(),
          txt;
        if (range.collapsed) {
          txt = this.document.createTextNode('p');
          range.insertNode(txt);
        }
        doJustify(range, align);
        if (txt) {
          range.setStartBefore(txt).collapse(true);
          domUtils.remove(txt);
        }
        range.select();
        return true;
      },
      queryCommandValue: function () {
        var startNode = this.selection.getStart(),
          value = domUtils.getComputedStyle(startNode, 'text-align');
        return defaultValue[value] ? value : 'left';
      },
      queryCommandState: function () {
        var start = this.selection.getStart(),
          cell = start && domUtils.findParentByTagName(start, ['td', 'th', 'caption'], true);
        return cell ? -1 : 0;
      },
    };
  };
  UE.plugins['font'] = function () {
    var me = this,
      fonts = {
        forecolor: 'color',
        backcolor: 'background-color',
        fontsize: 'font-size',
        fontfamily: 'font-family',
        underline: 'text-decoration',
        strikethrough: 'text-decoration',
        fontborder: 'border',
      },
      lang = me.getLang(),
      needCmd = { underline: 1, strikethrough: 1, fontborder: 1 },
      needSetChild = {
        forecolor: 'color',
        backcolor: 'background-color',
        fontsize: 'font-size',
        fontfamily: 'font-family',
      };
    me.setOpt({
      fontfamily: [
        { name: 'default', val: 'default' },
        { name: 'songti', val: 'SimSun' },
        { name: 'yahei', val: "'Microsoft YaHei'" },
        { name: 'kaiti', val: '楷体,楷体_GB2312,SimKai' },
        { name: 'heiti', val: '黑体,SimHei' },
        { name: 'lishu', val: '隶书,SimLi' },
        { name: 'arial', val: 'arial,helvetica,sans-serif' },
        { name: 'timesNewRoman', val: 'times new roman' },
      ],
      fontsize: [10, 11, 12, 14, 16, 18, 20, 24, 36],
    });
    function mergeWithParent(node) {
      var parent;
      while ((parent = node.parentNode)) {
        if (
          parent.tagName == 'SPAN' &&
          domUtils.getChildCount(parent, function (child) {
            return !domUtils.isBookmarkNode(child) && !domUtils.isBr(child);
          }) == 1
        ) {
          parent.style.cssText += node.style.cssText;
          domUtils.remove(node, true);
          node = parent;
        } else {
          break;
        }
      }
    }
    function mergeChild(rng, cmdName, value) {
      if (needSetChild[cmdName]) {
        rng.adjustmentBoundary();
        if (!rng.collapsed && rng.startContainer.nodeType == 1) {
          var start = rng.startContainer.childNodes[rng.startOffset];
          if (start && domUtils.isTagNode(start, 'span')) {
            var bk = rng.createBookmark();
            utils.each(domUtils.getElementsByTagName(start, 'span'), function (span) {
              if (!span.parentNode || domUtils.isBookmarkNode(span)) return;
              if (
                cmdName == 'backcolor' &&
                domUtils.getComputedStyle(span, 'background-color').toLowerCase() === value
              ) {
                return;
              }
              domUtils.removeStyle(span, needSetChild[cmdName]);
              if (span.style.cssText.replace(/^\s+$/, '').length == 0) {
                domUtils.remove(span, true);
              }
            });
            rng.moveToBookmark(bk);
          }
        }
      }
    }
    function mergesibling(rng, cmdName, value) {
      var collapsed = rng.collapsed,
        bk = rng.createBookmark(),
        common;
      if (collapsed) {
        common = bk.start.parentNode;
        while (dtd.$inline[common.tagName]) {
          common = common.parentNode;
        }
      } else {
        common = domUtils.getCommonAncestor(bk.start, bk.end);
      }
      utils.each(domUtils.getElementsByTagName(common, 'span'), function (span) {
        if (!span.parentNode || domUtils.isBookmarkNode(span)) return;
        if (/\s*border\s*:\s*none;?\s*/i.test(span.style.cssText)) {
          if (/^\s*border\s*:\s*none;?\s*$/.test(span.style.cssText)) {
            domUtils.remove(span, true);
          } else {
            domUtils.removeStyle(span, 'border');
          }
          return;
        }
        if (
          /border/i.test(span.style.cssText) &&
          span.parentNode.tagName == 'SPAN' &&
          /border/i.test(span.parentNode.style.cssText)
        ) {
          span.style.cssText = span.style.cssText.replace(/border[^:]*:[^;]+;?/gi, '');
        }
        if (!(cmdName == 'fontborder' && value == 'none')) {
          var next = span.nextSibling;
          while (next && next.nodeType == 1 && next.tagName == 'SPAN') {
            if (domUtils.isBookmarkNode(next) && cmdName == 'fontborder') {
              span.appendChild(next);
              next = span.nextSibling;
              continue;
            }
            if (next.style.cssText == span.style.cssText) {
              domUtils.moveChild(next, span);
              domUtils.remove(next);
            }
            if (span.nextSibling === next) break;
            next = span.nextSibling;
          }
        }
        var father = span.parentElement;
        try {
          if (father.style.textIndent && span.style.fontSize !== father.style.fontSize) {
            father.style.fontSize = span.style.fontSize;
          }
        } catch (error) {}
        mergeWithParent(span);
        if (browser.ie && browser.version > 8) {
          var parent = domUtils.findParent(span, function (n) {
            return n.tagName == 'SPAN' && /background-color/.test(n.style.cssText);
          });
          if (parent && !/background-color/.test(span.style.cssText)) {
            span.style.backgroundColor = parent.style.backgroundColor;
          }
        }
      });
      rng.moveToBookmark(bk);
      mergeChild(rng, cmdName, value);
    }
    me.addInputRule(function (root) {
      utils.each(root.getNodesByTagName('u s del font strike'), function (node) {
        if (node.tagName == 'font') {
          var cssStyle = [];
          for (var p in node.attrs) {
            switch (p) {
              case 'size':
                cssStyle.push(
                  'font-size:' +
                    ({ 1: '10', 2: '12', 3: '16', 4: '18', 5: '24', 6: '32', 7: '48' }[node.attrs[p]] ||
                      node.attrs[p]) +
                    'px',
                );
                break;
              case 'color':
                cssStyle.push('color:' + node.attrs[p]);
                break;
              case 'face':
                cssStyle.push('font-family:' + node.attrs[p]);
                break;
              case 'style':
                cssStyle.push(node.attrs[p]);
            }
          }
          node.attrs = { style: cssStyle.join(';') };
        } else {
          var val = node.tagName == 'u' ? 'underline' : 'line-through';
          node.attrs = { style: (node.getAttr('style') || '') + 'text-decoration:' + val + ';' };
        }
        node.tagName = 'span';
      });
    });
    for (var p in fonts) {
      (function (cmd, style) {
        UE.commands[cmd] = {
          execCommand: function (cmdName, value) {
            value =
              value ||
              (this.queryCommandState(cmdName)
                ? 'none'
                : cmdName === 'underline'
                  ? 'underline'
                  : cmdName === 'fontborder'
                    ? '1px solid #000'
                    : 'line-through');
            var me = this,
              range = this.selection.getRange(),
              text;
            if (value === 'default') {
              if (range.collapsed) {
                text = me.document.createTextNode('font');
                range.insertNode(text).select();
              }
              me.execCommand('removeFormat', 'span,a', style);
              if (text) {
                range.setStartBefore(text).collapse(true);
                domUtils.remove(text);
              }
              mergesibling(range, cmdName, value);
              range.select();
            } else {
              if (!range.collapsed) {
                if (needCmd[cmd] && me.queryCommandValue(cmd)) {
                  me.execCommand('removeFormat', 'span,a', style);
                }
                range = me.selection.getRange();
                range.applyInlineStyle('span', { style: style + ':' + value });
                mergesibling(range, cmdName, value);
                range.select();
              } else {
                var span = domUtils.findParentByTagName(range.startContainer, 'span', true);
                text = me.document.createTextNode('font');
                if (
                  span &&
                  !span.children.length &&
                  !span[browser.ie ? 'innerText' : 'textContent'].replace(fillCharReg, '').length
                ) {
                  range.insertNode(text);
                  if (needCmd[cmd]) {
                    range.selectNode(text).select();
                    me.execCommand('removeFormat', 'span,a', style, null);
                    span = domUtils.findParentByTagName(text, 'span', true);
                    range.setStartBefore(text);
                  }
                  span && (span.style.cssText += ';' + style + ':' + value);
                  range.collapse(true).select();
                } else {
                  range.insertNode(text);
                  range.selectNode(text).select();
                  span = range.document.createElement('span');
                  if (needCmd[cmd]) {
                    if (domUtils.findParentByTagName(text, 'a', true)) {
                      range.setStartBefore(text).setCursor();
                      domUtils.remove(text);
                      return;
                    }
                    me.execCommand('removeFormat', 'span,a', style);
                  }
                  span.style.cssText = style + ':' + value;
                  text.parentNode.insertBefore(span, text);
                  if (!browser.ie || (browser.ie && browser.version === 9)) {
                    var spanParent = span.parentNode;
                    while (!domUtils.isBlockElm(spanParent)) {
                      if (spanParent.tagName === 'SPAN') {
                        span.style.cssText = spanParent.style.cssText + ';' + span.style.cssText;
                      }
                      spanParent = spanParent.parentNode;
                    }
                  }
                  if (opera) {
                    setTimeout(function () {
                      range.setStart(span, 0).collapse(true);
                      mergesibling(range, cmdName, value);
                      range.select();
                    });
                  } else {
                    range.setStart(span, 0).collapse(true);
                    mergesibling(range, cmdName, value);
                    range.select();
                  }
                }
                domUtils.remove(text);
              }
            }
            return true;
          },
          queryCommandValue: function (cmdName) {
            var startNode = this.selection.getStart();
            var styleVal;
            if (cmdName === 'underline' || cmdName === 'strikethrough') {
              var tmpNode = startNode,
                value;
              while (tmpNode && !domUtils.isBlockElm(tmpNode) && !domUtils.isBody(tmpNode)) {
                if (tmpNode.nodeType === 1) {
                  value = domUtils.getComputedStyle(tmpNode, style);
                  if (value !== 'none') {
                    return value;
                  }
                }
                tmpNode = tmpNode.parentNode;
              }
              return 'none';
            } else if (cmdName === 'fontborder') {
              var tmp = startNode,
                val;
              while (tmp && dtd.$inline[tmp.tagName]) {
                if ((val = domUtils.getComputedStyle(tmp, 'border'))) {
                  if (/1px/.test(val) && /solid/.test(val)) {
                    return val;
                  }
                }
                tmp = tmp.parentNode;
              }
              return '';
            } else if (cmdName === 'FontSize') {
              styleVal = domUtils.getComputedStyle(startNode, style);
              tmp = /^([\d\.]+)(\w+)$/.exec(styleVal);
              if (tmp) {
                return Math.floor(tmp[1]) + tmp[2];
              }
              return styleVal;
            } else if (cmdName === 'FontFamily') {
              styleVal = domUtils.getComputedStyle(startNode, style);
              styleVal = styleVal.replace(/['"]/g, '');
              styleVal = styleVal.replace(/\s*,\s*/g, ',');
              var fontFamily = lang.fontfamily.default;
              var fontList = me.options['fontfamily'] || [];
              for (var i = 0; i < fontList.length; i++) {
                var v = fontList[i];
                if (v.val === styleVal) {
                  fontFamily = styleVal;
                  break;
                }
              }
              return fontFamily;
            }
            value = domUtils.getComputedStyle(startNode, style);
            return value;
          },
          queryCommandState: function (cmdName) {
            if (!needCmd[cmdName]) return 0;
            var val = this.queryCommandValue(cmdName);
            if (cmdName === 'fontborder') {
              return /1px/.test(val) && /solid/.test(val);
            } else {
              return cmdName === 'underline' ? /underline/.test(val) : /line\-through/.test(val);
            }
          },
        };
      })(p, fonts[p]);
    }
  };
  UE.plugins['link'] = function () {
    function optimize(range) {
      var start = range.startContainer,
        end = range.endContainer;
      if ((start = domUtils.findParentByTagName(start, 'a', true))) {
        range.setStartBefore(start);
      }
      if ((end = domUtils.findParentByTagName(end, 'a', true))) {
        range.setEndAfter(end);
      }
    }
    UE.commands['unlink'] = {
      execCommand: function () {
        var range = this.selection.getRange(),
          bookmark;
        if (range.collapsed && !domUtils.findParentByTagName(range.startContainer, 'a', true)) {
          return;
        }
        bookmark = range.createBookmark();
        optimize(range);
        range.removeInlineStyle('a').moveToBookmark(bookmark).select();
      },
      queryCommandState: function () {
        return !this.highlight && this.queryCommandValue('link') ? 0 : -1;
      },
    };
    function doLink(range, opt, me) {
      var rngClone = range.cloneRange(),
        link = me.queryCommandValue('link');
      optimize((range = range.adjustmentBoundary()));
      var start = range.startContainer;
      if (start.nodeType == 1 && link) {
        start = start.childNodes[range.startOffset];
        if (
          start &&
          start.nodeType == 1 &&
          start.tagName == 'A' &&
          /^(?:https?|ftp|file)\s*:\s*\/\//.test(start[browser.ie ? 'innerText' : 'textContent'])
        ) {
          start[browser.ie ? 'innerText' : 'textContent'] = utils.html(opt.textValue || opt.href);
        }
      }
      if (!rngClone.collapsed || link) {
        range.removeInlineStyle('a');
        rngClone = range.cloneRange();
      }
      if (rngClone.collapsed) {
        var a = range.document.createElement('a'),
          text = '';
        if (opt.textValue) {
          text = utils.html(opt.textValue);
          delete opt.textValue;
        } else {
          text = utils.html(opt.href);
        }
        domUtils.setAttributes(a, opt);
        start = domUtils.findParentByTagName(rngClone.startContainer, 'a', true);
        if (start && domUtils.isInNodeEndBoundary(rngClone, start)) {
          range.setStartAfter(start).collapse(true);
        }
        a[browser.ie ? 'innerText' : 'textContent'] = text;
        range.insertNode(a).selectNode(a);
      } else {
        range.applyInlineStyle('a', opt);
      }
    }
    UE.commands['link'] = {
      execCommand: function (cmdName, opt) {
        var range;
        opt._href && (opt._href = utils.unhtml(opt._href, /[<">]/g));
        opt.href && (opt.href = utils.unhtml(opt.href, /[<">]/g));
        opt.textValue && (opt.textValue = utils.unhtml(opt.textValue, /[<">]/g));
        doLink((range = this.selection.getRange()), opt, this);
        range.collapse().select(true);
      },
      queryCommandValue: function () {
        var range = this.selection.getRange(),
          node;
        if (range.collapsed) {
          node = range.startContainer;
          node = node.nodeType == 1 ? node : node.parentNode;
          if (
            node &&
            (node = domUtils.findParentByTagName(node, 'a', true)) &&
            !domUtils.isInNodeEndBoundary(range, node)
          ) {
            return node;
          }
        } else {
          range.shrinkBoundary();
          var start =
              range.startContainer.nodeType == 3 || !range.startContainer.childNodes[range.startOffset]
                ? range.startContainer
                : range.startContainer.childNodes[range.startOffset],
            end =
              range.endContainer.nodeType == 3 || range.endOffset == 0
                ? range.endContainer
                : range.endContainer.childNodes[range.endOffset - 1],
            common = range.getCommonAncestor();
          node = domUtils.findParentByTagName(common, 'a', true);
          if (!node && common.nodeType == 1) {
            var as = common.getElementsByTagName('a'),
              ps,
              pe;
            for (var i = 0, ci; (ci = as[i++]); ) {
              ((ps = domUtils.getPosition(ci, start)), (pe = domUtils.getPosition(ci, end)));
              if (
                (ps & domUtils.POSITION_FOLLOWING || ps & domUtils.POSITION_CONTAINS) &&
                (pe & domUtils.POSITION_PRECEDING || pe & domUtils.POSITION_CONTAINS)
              ) {
                node = ci;
                break;
              }
            }
          }
          return node;
        }
      },
      queryCommandState: function () {
        var img = this.selection.getRange().getClosedNode(),
          flag = img && (img.className == 'edui-faked-video' || img.className.indexOf('edui-upload-video') != -1);
        return flag ? -1 : 0;
      },
    };
  };
  UE.plugins['insertframe'] = function () {
    var me = this;
    function deleteIframe() {
      me._iframe && delete me._iframe;
    }
    me.addListener('selectionchange', function () {
      deleteIframe();
    });
  };
  UE.commands['scrawl'] = {
    queryCommandState: function () {
      return browser.ie && browser.version <= 8 ? -1 : 0;
    },
  };
  UE.plugins['removeformat'] = function () {
    var me = this;
    me.setOpt({
      removeFormatTags: 'b,big,code,del,dfn,em,font,i,ins,kbd,q,samp,small,span,strike,strong,sub,sup,tt,u,var',
      removeFormatAttributes: 'class,style,lang,width,height,align,hspace,valign',
    });
    me.commands['removeformat'] = {
      execCommand: function (cmdName, tags, style, attrs, notIncludeA) {
        var tagReg = new RegExp('^(?:' + (tags || this.options.removeFormatTags).replace(/,/g, '|') + ')$', 'i'),
          removeFormatAttributes = style ? [] : (attrs || this.options.removeFormatAttributes).split(','),
          range = new dom.Range(this.document),
          bookmark,
          node,
          parent,
          filter = function (node) {
            return node.nodeType == 1;
          };
        function isRedundantSpan(node) {
          if (node.nodeType == 3 || node.tagName.toLowerCase() != 'span') {
            return 0;
          }
          if (browser.ie) {
            var attrs = node.attributes;
            if (attrs.length) {
              for (var i = 0, l = attrs.length; i < l; i++) {
                if (attrs[i].specified) {
                  return 0;
                }
              }
              return 1;
            }
          }
          return !node.attributes.length;
        }
        function doRemove(range) {
          var bookmark1 = range.createBookmark();
          if (range.collapsed) {
            range.enlarge(true);
          }
          if (!notIncludeA) {
            var aNode = domUtils.findParentByTagName(range.startContainer, 'a', true);
            if (aNode) {
              range.setStartBefore(aNode);
            }
            aNode = domUtils.findParentByTagName(range.endContainer, 'a', true);
            if (aNode) {
              range.setEndAfter(aNode);
            }
          }
          bookmark = range.createBookmark();
          node = bookmark.start;
          while ((parent = node.parentNode) && !domUtils.isBlockElm(parent)) {
            domUtils.breakParent(node, parent);
            domUtils.clearEmptySibling(node);
          }
          if (bookmark.end) {
            node = bookmark.end;
            while ((parent = node.parentNode) && !domUtils.isBlockElm(parent)) {
              domUtils.breakParent(node, parent);
              domUtils.clearEmptySibling(node);
            }
            var current = domUtils.getNextDomNode(bookmark.start, false, filter),
              next;
            while (current) {
              if (current == bookmark.end) {
                break;
              }
              next = domUtils.getNextDomNode(current, true, filter);
              if (!dtd.$empty[current.tagName.toLowerCase()] && !domUtils.isBookmarkNode(current)) {
                if (tagReg.test(current.tagName)) {
                  if (style) {
                    domUtils.removeStyle(current, style);
                    if (isRedundantSpan(current) && style != 'text-decoration') {
                      domUtils.remove(current, true);
                    }
                  } else {
                    domUtils.remove(current, true);
                  }
                } else {
                  if (true) {
                    domUtils.removeAttributes(current, removeFormatAttributes);
                    if (isRedundantSpan(current)) {
                      domUtils.remove(current, true);
                    }
                  } else {
                  }
                }
              }
              current = next;
            }
          }
          var pN = bookmark.start.parentNode;
          if (domUtils.isBlockElm(pN) && !dtd.$tableContent[pN.tagName] && !dtd.$list[pN.tagName]) {
            domUtils.removeAttributes(pN, removeFormatAttributes);
          }
          pN = bookmark.end.parentNode;
          if (bookmark.end && domUtils.isBlockElm(pN) && !dtd.$tableContent[pN.tagName] && !dtd.$list[pN.tagName]) {
            domUtils.removeAttributes(pN, removeFormatAttributes);
          }
          range.moveToBookmark(bookmark).moveToBookmark(bookmark1);
          var node = range.startContainer,
            tmp,
            collapsed = range.collapsed;
          while (node.nodeType == 1 && domUtils.isEmptyNode(node) && dtd.$removeEmpty[node.tagName]) {
            tmp = node.parentNode;
            range.setStartBefore(node);
            if (range.startContainer === range.endContainer) {
              range.endOffset--;
            }
            domUtils.remove(node);
            node = tmp;
          }
          if (!collapsed) {
            node = range.endContainer;
            while (node.nodeType == 1 && domUtils.isEmptyNode(node) && dtd.$removeEmpty[node.tagName]) {
              tmp = node.parentNode;
              range.setEndBefore(node);
              domUtils.remove(node);
              node = tmp;
            }
          }
        }
        range = this.selection.getRange();
        doRemove(range);
        range.select();
      },
    };
  };
  UE.plugins['blockquote'] = function () {
    var me = this;
    function getObj(editor) {
      return domUtils.filterNodeList(editor.selection.getStartElementPath(), 'blockquote');
    }
    me.commands['blockquote'] = {
      execCommand: function (cmdName, attrs) {
        var range = this.selection.getRange(),
          obj = getObj(this),
          blockquote = dtd.blockquote,
          bookmark = range.createBookmark();
        if (obj) {
          var start = range.startContainer,
            startBlock = domUtils.isBlockElm(start)
              ? start
              : domUtils.findParent(start, function (node) {
                  return domUtils.isBlockElm(node);
                }),
            end = range.endContainer,
            endBlock = domUtils.isBlockElm(end)
              ? end
              : domUtils.findParent(end, function (node) {
                  return domUtils.isBlockElm(node);
                });
          startBlock = domUtils.findParentByTagName(startBlock, 'li', true) || startBlock;
          endBlock = domUtils.findParentByTagName(endBlock, 'li', true) || endBlock;
          if (
            startBlock.tagName == 'LI' ||
            startBlock.tagName == 'TD' ||
            startBlock === obj ||
            domUtils.isBody(startBlock)
          ) {
            domUtils.remove(obj, true);
          } else {
            domUtils.breakParent(startBlock, obj);
          }
          if (startBlock !== endBlock) {
            obj = domUtils.findParentByTagName(endBlock, 'blockquote');
            if (obj) {
              if (endBlock.tagName == 'LI' || endBlock.tagName == 'TD' || domUtils.isBody(endBlock)) {
                obj.parentNode && domUtils.remove(obj, true);
              } else {
                domUtils.breakParent(endBlock, obj);
              }
            }
          }
          var blockquotes = domUtils.getElementsByTagName(this.document, 'blockquote');
          for (var i = 0, bi; (bi = blockquotes[i++]); ) {
            if (!bi.childNodes.length) {
              domUtils.remove(bi);
            } else if (
              domUtils.getPosition(bi, startBlock) & domUtils.POSITION_FOLLOWING &&
              domUtils.getPosition(bi, endBlock) & domUtils.POSITION_PRECEDING
            ) {
              domUtils.remove(bi, true);
            }
          }
        } else {
          var tmpRange = range.cloneRange(),
            node = tmpRange.startContainer.nodeType == 1 ? tmpRange.startContainer : tmpRange.startContainer.parentNode,
            preNode = node,
            doEnd = 1;
          while (1) {
            if (domUtils.isBody(node)) {
              if (preNode !== node) {
                if (range.collapsed) {
                  tmpRange.selectNode(preNode);
                  doEnd = 0;
                } else {
                  tmpRange.setStartBefore(preNode);
                }
              } else {
                tmpRange.setStart(node, 0);
              }
              break;
            }
            if (!blockquote[node.tagName]) {
              if (range.collapsed) {
                tmpRange.selectNode(preNode);
              } else {
                tmpRange.setStartBefore(preNode);
              }
              break;
            }
            preNode = node;
            node = node.parentNode;
          }
          if (doEnd) {
            preNode =
              node =
              node =
                tmpRange.endContainer.nodeType == 1 ? tmpRange.endContainer : tmpRange.endContainer.parentNode;
            while (1) {
              if (domUtils.isBody(node)) {
                if (preNode !== node) {
                  tmpRange.setEndAfter(preNode);
                } else {
                  tmpRange.setEnd(node, node.childNodes.length);
                }
                break;
              }
              if (!blockquote[node.tagName]) {
                tmpRange.setEndAfter(preNode);
                break;
              }
              preNode = node;
              node = node.parentNode;
            }
          }
          node = range.document.createElement('blockquote');
          domUtils.setAttributes(node, attrs);
          node.appendChild(tmpRange.extractContents());
          tmpRange.insertNode(node);
          var childs = domUtils.getElementsByTagName(node, 'blockquote');
          for (var i = 0, ci; (ci = childs[i++]); ) {
            if (ci.parentNode) {
              domUtils.remove(ci, true);
            }
          }
        }
        range.moveToBookmark(bookmark).select();
      },
      queryCommandState: function () {
        return getObj(this) ? 1 : 0;
      },
    };
  };
  UE.commands['touppercase'] = UE.commands['tolowercase'] = {
    execCommand: function (cmd) {
      var me = this;
      var rng = me.selection.getRange();
      if (rng.collapsed) {
        return rng;
      }
      var bk = rng.createBookmark(),
        bkEnd = bk.end,
        filterFn = function (node) {
          return !domUtils.isBr(node) && !domUtils.isWhitespace(node);
        },
        curNode = domUtils.getNextDomNode(bk.start, false, filterFn);
      while (curNode && domUtils.getPosition(curNode, bkEnd) & domUtils.POSITION_PRECEDING) {
        if (curNode.nodeType == 3) {
          curNode.nodeValue = curNode.nodeValue[cmd == 'touppercase' ? 'toUpperCase' : 'toLowerCase']();
        }
        curNode = domUtils.getNextDomNode(curNode, true, filterFn);
        if (curNode === bkEnd) {
          break;
        }
      }
      rng.moveToBookmark(bk).select();
    },
  };
  UE.commands['indent'] = {
    execCommand: function () {
      var me = this,
        value = me.queryCommandState('indent') ? '0em' : me.options.indentValue || '2em';
      var pN = domUtils.filterNodeList(this.selection.getStartElementPath(), 'p h1 h2 h3 h4 h5 h6');
      try {
        me.execCommand('Paragraph', 'p', {
          style: 'text-indent:' + value + ';font-size:' + pN.firstChild.style.fontSize,
        });
      } catch (error) {
        me.execCommand('Paragraph', 'p', { style: 'text-indent:' + value });
      }
    },
    queryCommandState: function () {
      var pN = domUtils.filterNodeList(this.selection.getStartElementPath(), 'p h1 h2 h3 h4 h5 h6');
      return pN && pN.style.textIndent && parseInt(pN.style.textIndent) ? 1 : 0;
    },
  };
  UE.commands['print'] = {
    execCommand: function () {
      this.window.print();
    },
    notNeedUndo: 1,
  };
  UE.commands['preview'] = {
    execCommand: function () {
      var w = window.open('', '_blank', ''),
        d = w.document;
      d.open();
      d.write(
        '<!DOCTYPE html><html><head><meta charset="utf-8"/><script src="' +
          this.options.UEDITOR_HOME_URL +
          'ueditor.parse.js"><\/script><script>' +
          "setTimeout(function(){uParse('div',{rootPath: '" +
          this.options.UEDITOR_HOME_URL +
          "'})},300)" +
          '<\/script></head><body><div>' +
          this.getContent(null, null, true) +
          '</div></body></html>',
      );
      d.close();
    },
    notNeedUndo: 1,
  };
  UE.plugins['selectall'] = function () {
    var me = this;
    me.commands['selectall'] = {
      execCommand: function () {
        var me = this,
          body = me.body,
          range = me.selection.getRange();
        range.selectNodeContents(body);
        if (domUtils.isEmptyBlock(body)) {
          if (browser.opera && body.firstChild && body.firstChild.nodeType == 1) {
            range.setStartAtFirst(body.firstChild);
          }
          range.collapse(true);
        }
        range.select(true);
      },
      notNeedUndo: 1,
    };
    me.addshortcutkey({ selectAll: 'ctrl+65' });
  };
  UE.plugins['paragraph'] = function () {
    var me = this,
      block = domUtils.isBlockElm,
      notExchange = ['TD', 'LI', 'PRE'],
      doParagraph = function (range, style, attrs, sourceCmdName) {
        var bookmark = range.createBookmark(),
          filterFn = function (node) {
            return node.nodeType == 1
              ? node.tagName.toLowerCase() != 'br' && !domUtils.isBookmarkNode(node)
              : !domUtils.isWhitespace(node);
          },
          para;
        range.enlarge(true);
        var bookmark2 = range.createBookmark(),
          current = domUtils.getNextDomNode(bookmark2.start, false, filterFn),
          tmpRange = range.cloneRange(),
          tmpNode;
        while (current && !(domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)) {
          if (current.nodeType === 3 || !block(current)) {
            tmpRange.setStartBefore(current);
            while (current && current !== bookmark2.end && !block(current)) {
              tmpNode = current;
              current = domUtils.getNextDomNode(current, false, null, function (node) {
                return !block(node);
              });
            }
            tmpRange.setEndAfter(tmpNode);
            para = range.document.createElement(style);
            if (attrs) {
              domUtils.setAttributes(para, attrs);
              if (sourceCmdName && sourceCmdName === 'customstyle' && attrs.style) {
                para.style.cssText = attrs.style;
              }
            }
            para.appendChild(tmpRange.extractContents());
            if (domUtils.isEmptyNode(para)) {
              domUtils.fillChar(range.document, para);
            }
            tmpRange.insertNode(para);
            var parent = para.parentNode;
            if (
              block(parent) &&
              !domUtils.isBody(para.parentNode) &&
              utils.indexOf(notExchange, parent.tagName) === -1
            ) {
              if (!(sourceCmdName && sourceCmdName === 'customstyle')) {
                parent.getAttribute('dir') && para.setAttribute('dir', parent.getAttribute('dir'));
                parent.style.cssText && (para.style.cssText = parent.style.cssText + ';' + para.style.cssText);
                parent.style.textAlign && !para.style.textAlign && (para.style.textAlign = parent.style.textAlign);
                parent.style.textIndent && !para.style.textIndent && (para.style.textIndent = parent.style.textIndent);
                parent.style.padding && !para.style.padding && (para.style.padding = parent.style.padding);
              }
              if (attrs && /h\d/i.test(parent.tagName) && !/h\d/i.test(para.tagName)) {
                domUtils.setAttributes(parent, attrs);
                if (sourceCmdName && sourceCmdName === 'customstyle' && attrs.style) {
                  parent.style.cssText = attrs.style;
                }
                domUtils.remove(para.parentNode, true);
                para = parent;
              } else {
                domUtils.remove(para.parentNode, true);
              }
            }
            if (utils.indexOf(notExchange, parent.tagName) !== -1) {
              current = parent;
            } else {
              current = para;
            }
            current = domUtils.getNextDomNode(current, false, filterFn);
          } else {
            current = domUtils.getNextDomNode(current, true, filterFn);
          }
        }
        return range.moveToBookmark(bookmark2).moveToBookmark(bookmark);
      };
    me.setOpt('paragraph', { p: '', h1: '', h2: '', h3: '', h4: '', h5: '', h6: '' });
    me.commands['paragraph'] = {
      execCommand: function (cmdName, style, attrs, sourceCmdName) {
        var range = this.selection.getRange();
        if (range.collapsed) {
          var txt = this.document.createTextNode('p');
          range.insertNode(txt);
          if (browser.ie) {
            var node = txt.previousSibling;
            if (node && domUtils.isWhitespace(node)) {
              domUtils.remove(node);
            }
            node = txt.nextSibling;
            if (node && domUtils.isWhitespace(node)) {
              domUtils.remove(node);
            }
          }
        }
        range = doParagraph(range, style, attrs, sourceCmdName);
        if (txt) {
          range.setStartBefore(txt).collapse(true);
          pN = txt.parentNode;
          domUtils.remove(txt);
          if (domUtils.isBlockElm(pN) && domUtils.isEmptyNode(pN)) {
            domUtils.fillNode(this.document, pN);
          }
        }
        if (browser.gecko && range.collapsed && range.startContainer.nodeType === 1) {
          var child = range.startContainer.childNodes[range.startOffset];
          if (child && child.nodeType === 1 && child.tagName.toLowerCase() === style) {
            range.setStart(child, 0).collapse(true);
          }
        }
        range.select();
        return true;
      },
      queryCommandValue: function () {
        var node = domUtils.filterNodeList(this.selection.getStartElementPath(), 'p h1 h2 h3 h4 h5 h6');
        return node ? node.tagName.toLowerCase() : '';
      },
    };
  };
  (function () {
    var block = domUtils.isBlockElm,
      getObj = function (editor) {
        return domUtils.filterNodeList(editor.selection.getStartElementPath(), function (n) {
          return n && n.nodeType == 1 && n.getAttribute('dir');
        });
      },
      doDirectionality = function (range, editor, forward) {
        var bookmark,
          filterFn = function (node) {
            return node.nodeType == 1 ? !domUtils.isBookmarkNode(node) : !domUtils.isWhitespace(node);
          },
          obj = getObj(editor);
        if (obj && range.collapsed) {
          obj.setAttribute('dir', forward);
          return range;
        }
        bookmark = range.createBookmark();
        range.enlarge(true);
        var bookmark2 = range.createBookmark(),
          current = domUtils.getNextDomNode(bookmark2.start, false, filterFn),
          tmpRange = range.cloneRange(),
          tmpNode;
        while (current && !(domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)) {
          if (current.nodeType == 3 || !block(current)) {
            tmpRange.setStartBefore(current);
            while (current && current !== bookmark2.end && !block(current)) {
              tmpNode = current;
              current = domUtils.getNextDomNode(current, false, null, function (node) {
                return !block(node);
              });
            }
            tmpRange.setEndAfter(tmpNode);
            var common = tmpRange.getCommonAncestor();
            if (!domUtils.isBody(common) && block(common)) {
              common.setAttribute('dir', forward);
              current = common;
            } else {
              var p = range.document.createElement('p');
              p.setAttribute('dir', forward);
              var frag = tmpRange.extractContents();
              p.appendChild(frag);
              tmpRange.insertNode(p);
              current = p;
            }
            current = domUtils.getNextDomNode(current, false, filterFn);
          } else {
            current = domUtils.getNextDomNode(current, true, filterFn);
          }
        }
        return range.moveToBookmark(bookmark2).moveToBookmark(bookmark);
      };
    UE.commands['directionality'] = {
      execCommand: function (cmdName, forward) {
        var range = this.selection.getRange();
        if (range.collapsed) {
          var txt = this.document.createTextNode('d');
          range.insertNode(txt);
        }
        doDirectionality(range, this, forward);
        if (txt) {
          range.setStartBefore(txt).collapse(true);
          domUtils.remove(txt);
        }
        range.select();
        return true;
      },
      queryCommandValue: function () {
        var node = getObj(this);
        return node ? node.getAttribute('dir') : 'ltr';
      },
    };
  })();
  UE.plugins['horizontal'] = function () {
    var me = this;
    me.commands['horizontal'] = {
      execCommand: function (cmdName) {
        var me = this;
        if (me.queryCommandState(cmdName) !== -1) {
          me.execCommand('insertHtml', '<hr>');
          var range = me.selection.getRange(),
            start = range.startContainer;
          if (start.nodeType == 1 && !start.childNodes[range.startOffset]) {
            var tmp;
            if ((tmp = start.childNodes[range.startOffset - 1])) {
              if (tmp.nodeType == 1 && tmp.tagName == 'HR') {
                if (me.options.enterTag == 'p') {
                  tmp = me.document.createElement('p');
                  range.insertNode(tmp);
                  range.setStart(tmp, 0).setCursor();
                } else {
                  tmp = me.document.createElement('br');
                  range.insertNode(tmp);
                  range.setStartBefore(tmp).setCursor();
                }
              }
            }
          }
          return true;
        }
      },
      queryCommandState: function () {
        return domUtils.filterNodeList(this.selection.getStartElementPath(), 'table') ? -1 : 0;
      },
    };
    me.addListener('delkeydown', function (name, evt) {
      var rng = this.selection.getRange();
      rng.txtToElmBoundary(true);
      if (domUtils.isStartInblock(rng)) {
        var tmpNode = rng.startContainer;
        var pre = tmpNode.previousSibling;
        if (pre && domUtils.isTagNode(pre, 'hr')) {
          domUtils.remove(pre);
          rng.select();
          domUtils.preventDefault(evt);
          return true;
        }
      }
    });
  };
  UE.commands['time'] = UE.commands['date'] = {
    execCommand: function (cmd, format) {
      var date = new Date();
      function formatTime(date, format) {
        var hh = ('0' + date.getHours()).slice(-2),
          ii = ('0' + date.getMinutes()).slice(-2),
          ss = ('0' + date.getSeconds()).slice(-2);
        format = format || 'hh:ii:ss';
        return format.replace(/hh/gi, hh).replace(/ii/gi, ii).replace(/ss/gi, ss);
      }
      function formatDate(date, format) {
        var yyyy = ('000' + date.getFullYear()).slice(-4),
          yy = yyyy.slice(-2),
          mm = ('0' + (date.getMonth() + 1)).slice(-2),
          dd = ('0' + date.getDate()).slice(-2);
        format = format || 'yyyy-mm-dd';
        return format.replace(/yyyy/gi, yyyy).replace(/yy/gi, yy).replace(/mm/gi, mm).replace(/dd/gi, dd);
      }
      this.execCommand('insertHtml', cmd == 'time' ? formatTime(date, format) : formatDate(date, format));
    },
  };
  UE.plugins['rowspacing'] = function () {
    var me = this;
    me.setOpt({ rowspacingtop: ['5', '10', '15', '20', '25'], rowspacingbottom: ['5', '10', '15', '20', '25'] });
    me.commands['rowspacing'] = {
      execCommand: function (cmdName, value, dir) {
        this.execCommand('paragraph', 'p', { style: 'margin-' + dir + ':' + value + 'px' });
        return true;
      },
      queryCommandValue: function (cmdName, dir) {
        var pN = domUtils.filterNodeList(this.selection.getStartElementPath(), function (node) {
            return domUtils.isBlockElm(node);
          }),
          value;
        if (pN) {
          value = domUtils.getComputedStyle(pN, 'margin-' + dir).replace(/[^\d]/g, '');
          return !value ? 0 : value;
        }
        return 0;
      },
    };
  };
  UE.plugins['lineheight'] = function () {
    var me = this;
    me.setOpt({ lineheight: ['1', '1.5', '1.75', '2', '3', '4', '5'] });
    me.commands['lineheight'] = {
      execCommand: function (cmdName, value) {
        this.execCommand('paragraph', 'p', { style: 'line-height:' + (value == '1' ? 'normal' : value + 'em') });
        return true;
      },
      queryCommandValue: function () {
        var pN = domUtils.filterNodeList(this.selection.getStartElementPath(), function (node) {
          return domUtils.isBlockElm(node);
        });
        if (pN) {
          var value = domUtils.getComputedStyle(pN, 'line-height');
          return value == 'normal' ? 1 : value.replace(/[^\d.]*/gi, '');
        }
      },
    };
  };
  UE.plugins['insertcode'] = function () {
    var me = this;
    me.setOpt('insertcode', {
      as3: 'ActionScript3',
      bash: 'Bash/Shell',
      cpp: 'C/C++',
      css: 'Css',
      'c#': 'C#',
      delphi: 'Delphi',
      erlang: 'Erlang',
      groovy: 'Groovy',
      html: 'Html',
      java: 'Java',
      js: 'Javascript',
      pl: 'Perl',
      php: 'PHP',
      plain: 'Text',
      ps: 'PowerShell',
      python: 'Python',
      ruby: 'Ruby',
      scala: 'Scala',
      sql: 'SQL',
      vb: 'VB',
      xml: 'XML',
      mind: 'Mind',
    });
    me.commands['insertcode'] = {
      execCommand: function (cmd, lang) {
        var me = this,
          rng = me.selection.getRange(),
          pre = domUtils.findParentByTagName(rng.startContainer, 'pre', true);
        if (pre) {
          pre.className = 'brush:' + lang + ';toolbar:false;';
        } else {
          var code = '';
          if (rng.collapsed) {
            code = browser.ie && browser.ie11below ? (browser.version <= 8 ? '&nbsp;' : '') : '<br/>';
          } else {
            var frag = rng.extractContents();
            var div = me.document.createElement('div');
            div.appendChild(frag);
            utils.each(
              UE.filterNode(UE.htmlparser(div.innerHTML.replace(/[\r\t]/g, '')), me.options.filterTxtRules).children,
              function (node) {
                if (browser.ie && browser.ie11below && browser.version > 8) {
                  if (node.type == 'element') {
                    if (node.tagName == 'br') {
                      code += '\n';
                    } else if (!dtd.$empty[node.tagName]) {
                      utils.each(node.children, function (cn) {
                        if (cn.type == 'element') {
                          if (cn.tagName == 'br') {
                            code += '\n';
                          } else if (!dtd.$empty[node.tagName]) {
                            code += cn.innerText();
                          }
                        } else {
                          code += cn.data;
                        }
                      });
                      if (!/\n$/.test(code)) {
                        code += '\n';
                      }
                    }
                  } else {
                    code += node.data + '\n';
                  }
                  if (!node.nextSibling() && /\n$/.test(code)) {
                    code = code.replace(/\n$/, '');
                  }
                } else {
                  if (browser.ie && browser.ie11below) {
                    if (node.type == 'element') {
                      if (node.tagName == 'br') {
                        code += '<br>';
                      } else if (!dtd.$empty[node.tagName]) {
                        utils.each(node.children, function (cn) {
                          if (cn.type == 'element') {
                            if (cn.tagName == 'br') {
                              code += '<br>';
                            } else if (!dtd.$empty[node.tagName]) {
                              code += cn.innerText();
                            }
                          } else {
                            code += cn.data;
                          }
                        });
                        if (!/br>$/.test(code)) {
                          code += '<br>';
                        }
                      }
                    } else {
                      code += node.data + '<br>';
                    }
                    if (!node.nextSibling() && /<br>$/.test(code)) {
                      code = code.replace(/<br>$/, '');
                    }
                  } else {
                    code += node.type == 'element' ? (dtd.$empty[node.tagName] ? '' : node.innerText()) : node.data;
                    if (!/br\/?\s*>$/.test(code)) {
                      if (!node.nextSibling()) return;
                      code += '<br>';
                    }
                  }
                }
              },
            );
          }
          me.execCommand(
            'inserthtml',
            '<pre id="coder"class="brush:' + lang + ';toolbar:false">' + code + '</pre>',
            true,
          );
          pre = me.document.getElementById('coder');
          domUtils.removeAttributes(pre, 'id');
          var tmpNode = pre.previousSibling;
          if (
            tmpNode &&
            ((tmpNode.nodeType == 3 && tmpNode.nodeValue.length == 1 && browser.ie && browser.version == 6) ||
              domUtils.isEmptyBlock(tmpNode))
          ) {
            domUtils.remove(tmpNode);
          }
          var rng = me.selection.getRange();
          if (domUtils.isEmptyBlock(pre)) {
            rng.setStart(pre, 0).setCursor(false, true);
          } else {
            rng.selectNodeContents(pre).select();
          }
        }
      },
      queryCommandValue: function () {
        var path = this.selection.getStartElementPath();
        var lang = '';
        utils.each(path, function (node) {
          if (node.nodeName == 'PRE') {
            var match = node.className.match(/brush:([^;]+)/);
            lang = match && match[1] ? match[1] : '';
            return false;
          }
        });
        return lang;
      },
    };
    me.addInputRule(function (root) {
      utils.each(root.getNodesByTagName('pre'), function (pre) {
        var brs = pre.getNodesByTagName('br');
        if (brs.length) {
          browser.ie &&
            browser.ie11below &&
            browser.version > 8 &&
            utils.each(brs, function (br) {
              var txt = UE.uNode.createText('\n');
              br.parentNode.insertBefore(txt, br);
              br.parentNode.removeChild(br);
            });
          return;
        }
        if (browser.ie && browser.ie11below && browser.version > 8) return;
        var code = pre.innerText().split(/\n/);
        pre.innerHTML('');
        utils.each(code, function (c) {
          if (c.length) {
            pre.appendChild(UE.uNode.createText(c));
          }
          pre.appendChild(UE.uNode.createElement('br'));
        });
      });
    });
    me.addOutputRule(function (root) {
      utils.each(root.getNodesByTagName('pre'), function (pre) {
        var code = '';
        utils.each(pre.children, function (n) {
          if (n.type == 'text') {
            code += n.data.replace(/[ ]/g, '&nbsp;').replace(/\n$/, '');
          } else {
            if (n.tagName == 'br') {
              code += '\n';
            } else {
              code += !dtd.$empty[n.tagName] ? '' : n.innerText();
            }
          }
        });
        pre.innerText(code.replace(/(&nbsp;|\n)+$/, ''));
      });
    });
    me.notNeedCodeQuery = {
      help: 1,
      undo: 1,
      redo: 1,
      source: 1,
      print: 1,
      searchreplace: 1,
      fullscreen: 1,
      preview: 1,
      insertparagraph: 1,
      elementpath: 1,
      insertcode: 1,
      inserthtml: 1,
      selectall: 1,
    };
    var orgQuery = me.queryCommandState;
    me.queryCommandState = function (cmd) {
      var me = this;
      if (!me.notNeedCodeQuery[cmd.toLowerCase()] && me.selection && me.queryCommandValue('insertcode')) {
        return -1;
      }
      return UE.Editor.prototype.queryCommandState.apply(this, arguments);
    };
    me.addListener('beforeenterkeydown', function () {
      var rng = me.selection.getRange();
      var pre = domUtils.findParentByTagName(rng.startContainer, 'pre', true);
      if (pre) {
        me.fireEvent('saveScene');
        if (!rng.collapsed) {
          rng.deleteContents();
        }
        if (!browser.ie || browser.ie9above) {
          var tmpNode = me.document.createElement('br'),
            pre;
          rng.insertNode(tmpNode).setStartAfter(tmpNode).collapse(true);
          var next = tmpNode.nextSibling;
          if (!next && (!browser.ie || browser.version > 10)) {
            rng.insertNode(tmpNode.cloneNode(false));
          } else {
            rng.setStartAfter(tmpNode);
          }
          pre = tmpNode.previousSibling;
          var tmp;
          while (pre) {
            tmp = pre;
            pre = pre.previousSibling;
            if (!pre || pre.nodeName == 'BR') {
              pre = tmp;
              break;
            }
          }
          if (pre) {
            var str = '';
            while (pre && pre.nodeName != 'BR' && new RegExp('^[\\s' + domUtils.fillChar + ']*$').test(pre.nodeValue)) {
              str += pre.nodeValue;
              pre = pre.nextSibling;
            }
            if (pre.nodeName != 'BR') {
              var match = pre.nodeValue.match(new RegExp('^([\\s' + domUtils.fillChar + ']+)'));
              if (match && match[1]) {
                str += match[1];
              }
            }
            if (str) {
              str = me.document.createTextNode(str);
              rng.insertNode(str).setStartAfter(str);
            }
          }
          rng.collapse(true).select(true);
        } else {
          if (browser.version > 8) {
            var txt = me.document.createTextNode('\n');
            var start = rng.startContainer;
            if (rng.startOffset == 0) {
              var preNode = start.previousSibling;
              if (preNode) {
                rng.insertNode(txt);
                var fillchar = me.document.createTextNode(' ');
                rng.setStartAfter(txt).insertNode(fillchar).setStart(fillchar, 0).collapse(true).select(true);
              }
            } else {
              rng.insertNode(txt).setStartAfter(txt);
              var fillchar = me.document.createTextNode(' ');
              start = rng.startContainer.childNodes[rng.startOffset];
              if (start && !/^\n/.test(start.nodeValue)) {
                rng.setStartBefore(txt);
              }
              rng.insertNode(fillchar).setStart(fillchar, 0).collapse(true).select(true);
            }
          } else {
            var tmpNode = me.document.createElement('br');
            rng.insertNode(tmpNode);
            rng.insertNode(me.document.createTextNode(domUtils.fillChar));
            rng.setStartAfter(tmpNode);
            pre = tmpNode.previousSibling;
            var tmp;
            while (pre) {
              tmp = pre;
              pre = pre.previousSibling;
              if (!pre || pre.nodeName == 'BR') {
                pre = tmp;
                break;
              }
            }
            if (pre) {
              var str = '';
              while (pre && pre.nodeName != 'BR' && new RegExp('^[ ' + domUtils.fillChar + ']*$').test(pre.nodeValue)) {
                str += pre.nodeValue;
                pre = pre.nextSibling;
              }
              if (pre.nodeName != 'BR') {
                var match = pre.nodeValue.match(new RegExp('^([ ' + domUtils.fillChar + ']+)'));
                if (match && match[1]) {
                  str += match[1];
                }
              }
              str = me.document.createTextNode(str);
              rng.insertNode(str).setStartAfter(str);
            }
            rng.collapse(true).select();
          }
        }
        me.fireEvent('saveScene');
        return true;
      }
    });
    me.addListener('tabkeydown', function (cmd, evt) {
      var rng = me.selection.getRange();
      var pre = domUtils.findParentByTagName(rng.startContainer, 'pre', true);
      if (pre) {
        me.fireEvent('saveScene');
        if (evt.shiftKey) {
        } else {
          if (!rng.collapsed) {
            var bk = rng.createBookmark();
            var start = bk.start.previousSibling;
            while (start) {
              if (pre.firstChild === start && !domUtils.isBr(start)) {
                pre.insertBefore(me.document.createTextNode('    '), start);
                break;
              }
              if (domUtils.isBr(start)) {
                pre.insertBefore(me.document.createTextNode('    '), start.nextSibling);
                break;
              }
              start = start.previousSibling;
            }
            var end = bk.end;
            start = bk.start.nextSibling;
            if (pre.firstChild === bk.start) {
              pre.insertBefore(me.document.createTextNode('    '), start.nextSibling);
            }
            while (start && start !== end) {
              if (domUtils.isBr(start) && start.nextSibling) {
                if (start.nextSibling === end) {
                  break;
                }
                pre.insertBefore(me.document.createTextNode('    '), start.nextSibling);
              }
              start = start.nextSibling;
            }
            rng.moveToBookmark(bk).select();
          } else {
            var tmpNode = me.document.createTextNode('    ');
            rng.insertNode(tmpNode).setStartAfter(tmpNode).collapse(true).select(true);
          }
        }
        me.fireEvent('saveScene');
        return true;
      }
    });
    me.addListener('beforeinserthtml', function (evtName, html) {
      var me = this,
        rng = me.selection.getRange(),
        pre = domUtils.findParentByTagName(rng.startContainer, 'pre', true);
      if (pre) {
        if (!rng.collapsed) {
          rng.deleteContents();
        }
        var htmlstr = '';
        if (browser.ie && browser.version > 8) {
          utils.each(UE.filterNode(UE.htmlparser(html), me.options.filterTxtRules).children, function (node) {
            if (node.type == 'element') {
              if (node.tagName == 'br') {
                htmlstr += '\n';
              } else if (!dtd.$empty[node.tagName]) {
                utils.each(node.children, function (cn) {
                  if (cn.type == 'element') {
                    if (cn.tagName == 'br') {
                      htmlstr += '\n';
                    } else if (!dtd.$empty[node.tagName]) {
                      htmlstr += cn.innerText();
                    }
                  } else {
                    htmlstr += cn.data;
                  }
                });
                if (!/\n$/.test(htmlstr)) {
                  htmlstr += '\n';
                }
              }
            } else {
              htmlstr += node.data + '\n';
            }
            if (!node.nextSibling() && /\n$/.test(htmlstr)) {
              htmlstr = htmlstr.replace(/\n$/, '');
            }
          });
          var tmpNode = me.document.createTextNode(utils.html(htmlstr.replace(/&nbsp;/g, ' ')));
          rng.insertNode(tmpNode).selectNode(tmpNode).select();
        } else {
          var frag = me.document.createDocumentFragment();
          utils.each(UE.filterNode(UE.htmlparser(html), me.options.filterTxtRules).children, function (node) {
            if (node.type == 'element') {
              if (node.tagName == 'br') {
                frag.appendChild(me.document.createElement('br'));
              } else if (!dtd.$empty[node.tagName]) {
                utils.each(node.children, function (cn) {
                  if (cn.type == 'element') {
                    if (cn.tagName == 'br') {
                      frag.appendChild(me.document.createElement('br'));
                    } else if (!dtd.$empty[node.tagName]) {
                      frag.appendChild(me.document.createTextNode(utils.html(cn.innerText().replace(/&nbsp;/g, ' '))));
                    }
                  } else {
                    frag.appendChild(me.document.createTextNode(utils.html(cn.data.replace(/&nbsp;/g, ' '))));
                  }
                });
                if (frag.lastChild.nodeName != 'BR') {
                  frag.appendChild(me.document.createElement('br'));
                }
              }
            } else {
              frag.appendChild(me.document.createTextNode(utils.html(node.data.replace(/&nbsp;/g, ' '))));
            }
            if (!node.nextSibling() && frag.lastChild.nodeName == 'BR') {
              frag.removeChild(frag.lastChild);
            }
          });
          rng.insertNode(frag).select();
        }
        return true;
      }
    });
    me.addListener('keydown', function (cmd, evt) {
      var me = this,
        keyCode = evt.keyCode || evt.which;
      if (keyCode == 40) {
        var rng = me.selection.getRange(),
          pre,
          start = rng.startContainer;
        if (
          rng.collapsed &&
          (pre = domUtils.findParentByTagName(rng.startContainer, 'pre', true)) &&
          !pre.nextSibling
        ) {
          var last = pre.lastChild;
          while (last && last.nodeName == 'BR') {
            last = last.previousSibling;
          }
          if (last === start || (rng.startContainer === pre && rng.startOffset == pre.childNodes.length)) {
            me.execCommand('insertparagraph');
            domUtils.preventDefault(evt);
          }
        }
      }
    });
    me.addListener('delkeydown', function (type, evt) {
      var rng = this.selection.getRange();
      rng.txtToElmBoundary(true);
      var start = rng.startContainer;
      if (domUtils.isTagNode(start, 'pre') && rng.collapsed && domUtils.isStartInblock(rng)) {
        var p = me.document.createElement('p');
        domUtils.fillNode(me.document, p);
        start.parentNode.insertBefore(p, start);
        domUtils.remove(start);
        rng.setStart(p, 0).setCursor(false, true);
        domUtils.preventDefault(evt);
        return true;
      }
    });
  };
  UE.commands['cleardoc'] = {
    execCommand: function (cmdName) {
      var me = this,
        enterTag = me.options.enterTag,
        range = me.selection.getRange();
      if (enterTag == 'br') {
        me.body.innerHTML = '<br/>';
        range.setStart(me.body, 0).setCursor();
      } else {
        me.body.innerHTML = '<p>' + (ie ? '' : '<br/>') + '</p>';
        range.setStart(me.body.firstChild, 0).setCursor(false, true);
      }
      setTimeout(function () {
        me.fireEvent('clearDoc');
      }, 0);
    },
  };
  UE.plugin.register('anchor', function () {
    return {
      bindEvents: {
        ready: function () {
          utils.cssRule(
            'anchor',
            ".anchorclass{background: url('" +
              this.options.themePath +
              this.options.theme +
              "/images/anchor.gif') no-repeat scroll left center transparent;cursor: auto;display: inline-block;height: 16px;width: 15px;}",
            this.document,
          );
        },
      },
      outputRule: function (root) {
        utils.each(root.getNodesByTagName('img'), function (a) {
          var val;
          if ((val = a.getAttr('anchorname'))) {
            a.tagName = 'a';
            a.setAttr({ anchorname: '', name: val, class: '' });
          }
        });
      },
      inputRule: function (root) {
        utils.each(root.getNodesByTagName('a'), function (a) {
          var val;
          if ((val = a.getAttr('name')) && !a.getAttr('href')) {
            if (/^\_Toc\d+$/.test(val)) {
              a.parentNode.removeChild(a);
              return;
            }
            a.tagName = 'img';
            a.setAttr({ anchorname: a.getAttr('name'), class: 'anchorclass' });
            a.setAttr('name');
          }
        });
      },
      commands: {
        anchor: {
          execCommand: function (cmd, name) {
            var range = this.selection.getRange(),
              img = range.getClosedNode();
            if (img && img.getAttribute('anchorname')) {
              if (name) {
                img.setAttribute('anchorname', name);
              } else {
                range.setStartBefore(img).setCursor();
                domUtils.remove(img);
              }
            } else {
              if (name) {
                var anchor = this.document.createElement('img');
                range.collapse(true);
                domUtils.setAttributes(anchor, { anchorname: name, class: 'anchorclass' });
                range.insertNode(anchor).setStartAfter(anchor).setCursor(false, true);
              }
            }
          },
        },
      },
    };
  });
  UE.plugins['wordcount'] = function () {
    var me = this;
    me.setOpt('wordCount', true);
    me.addListener('contentchange', function () {
      me.fireEvent('wordcount');
    });
    var timer;
    me.addListener('ready', function () {
      var me = this;
      domUtils.on(me.body, 'keyup', function (evt) {
        var code = evt.keyCode || evt.which,
          ignores = { 16: 1, 18: 1, 20: 1, 37: 1, 38: 1, 39: 1, 40: 1 };
        if (code in ignores) return;
        clearTimeout(timer);
        timer = setTimeout(function () {
          me.fireEvent('wordcount');
        }, 200);
      });
    });
  };
  UE.plugins['pagebreak'] = function () {
    var me = this,
      notBreakTags = ['td'];
    me.setOpt('pageBreakTag', '_ueditor_page_break_tag_');
    function fillNode(node) {
      if (domUtils.isEmptyBlock(node)) {
        var firstChild = node.firstChild,
          tmpNode;
        while (firstChild && firstChild.nodeType == 1 && domUtils.isEmptyBlock(firstChild)) {
          tmpNode = firstChild;
          firstChild = firstChild.firstChild;
        }
        !tmpNode && (tmpNode = node);
        domUtils.fillNode(me.document, tmpNode);
      }
    }
    me.ready(function () {
      utils.cssRule(
        'pagebreak',
        '.pagebreak{display:block;clear:both !important;cursor:default !important;width: 100% !important;margin:0;}',
        me.document,
      );
    });
    function isHr(node) {
      return node && node.nodeType == 1 && node.tagName == 'HR' && node.className == 'pagebreak';
    }
    me.addInputRule(function (root) {
      root.traversal(function (node) {
        if (node.type == 'text' && node.data == me.options.pageBreakTag) {
          var hr = UE.uNode.createElement(
            '<hr class="pagebreak" noshade="noshade" size="5" style="-webkit-user-select: none;">',
          );
          node.parentNode.insertBefore(hr, node);
          node.parentNode.removeChild(node);
        }
      });
    });
    me.addOutputRule(function (node) {
      utils.each(node.getNodesByTagName('hr'), function (n) {
        if (n.getAttr('class') == 'pagebreak') {
          var txt = UE.uNode.createText(me.options.pageBreakTag);
          n.parentNode.insertBefore(txt, n);
          n.parentNode.removeChild(n);
        }
      });
    });
    me.commands['pagebreak'] = {
      execCommand: function () {
        var range = me.selection.getRange(),
          hr = me.document.createElement('hr');
        domUtils.setAttributes(hr, { class: 'pagebreak', noshade: 'noshade', size: '5' });
        domUtils.unSelectable(hr);
        var node = domUtils.findParentByTagName(range.startContainer, notBreakTags, true),
          parents = [],
          pN;
        if (node) {
          switch (node.tagName) {
            case 'TD':
              pN = node.parentNode;
              if (!pN.previousSibling) {
                var table = domUtils.findParentByTagName(pN, 'table');
                table.parentNode.insertBefore(hr, table);
                parents = domUtils.findParents(hr, true);
              } else {
                pN.parentNode.insertBefore(hr, pN);
                parents = domUtils.findParents(hr);
              }
              pN = parents[1];
              if (hr !== pN) {
                domUtils.breakParent(hr, pN);
              }
              me.fireEvent('afteradjusttable', me.document);
          }
        } else {
          if (!range.collapsed) {
            range.deleteContents();
            var start = range.startContainer;
            while (!domUtils.isBody(start) && domUtils.isBlockElm(start) && domUtils.isEmptyNode(start)) {
              range.setStartBefore(start).collapse(true);
              domUtils.remove(start);
              start = range.startContainer;
            }
          }
          range.insertNode(hr);
          var pN = hr.parentNode,
            nextNode;
          while (!domUtils.isBody(pN)) {
            domUtils.breakParent(hr, pN);
            nextNode = hr.nextSibling;
            if (nextNode && domUtils.isEmptyBlock(nextNode)) {
              domUtils.remove(nextNode);
            }
            pN = hr.parentNode;
          }
          nextNode = hr.nextSibling;
          var pre = hr.previousSibling;
          if (isHr(pre)) {
            domUtils.remove(pre);
          } else {
            pre && fillNode(pre);
          }
          if (!nextNode) {
            var p = me.document.createElement('p');
            hr.parentNode.appendChild(p);
            domUtils.fillNode(me.document, p);
            range.setStart(p, 0).collapse(true);
          } else {
            if (isHr(nextNode)) {
              domUtils.remove(nextNode);
            } else {
              fillNode(nextNode);
            }
            range.setEndAfter(hr).collapse(false);
          }
          range.select(true);
        }
      },
    };
  };
  UE.plugin.register('wordimage', function () {
    var me = this,
      images = [];
    this.addListener('click', function (type, evt) {
      var el = evt.target || evt.srcElement;
      if ('IMG' == el.tagName && el.getAttribute('data-word-image')) {
        me.ui._dialogs.wordimageDialog && me.ui._dialogs.wordimageDialog.open();
      }
    });
    return {
      commands: {
        wordimage: {
          execCommand: function () {
            var images = domUtils.getElementsByTagName(me.body, 'img');
            var urlList = [];
            for (var i = 0, ci; (ci = images[i++]); ) {
              var url = ci.getAttribute('data-word-image');
              url && urlList.push(url);
            }
            return urlList;
          },
          queryCommandState: function () {
            images = domUtils.getElementsByTagName(me.body, 'img');
            for (var i = 0, ci; (ci = images[i++]); ) {
              if (ci.getAttribute('data-word-image')) {
                return 1;
              }
            }
            return -1;
          },
          notNeedUndo: true,
        },
      },
      inputRule: function (root) {
        utils.each(root.getNodesByTagName('img'), function (img) {
          var attrs = img.attrs,
            flag = parseInt(attrs.width) < 128 || parseInt(attrs.height) < 43,
            opt = me.options,
            src = opt.UEDITOR_HOME_URL + 'themes/default/images/spacer.gif';
          if (attrs['src'] && /^(?:(file:\/+))/.test(attrs['src'])) {
            img.setAttr({
              width: attrs.width,
              height: attrs.height,
              alt: attrs.alt,
              'data-word-image': attrs.src,
              src: src,
              style:
                'background:url(' +
                (flag
                  ? opt.themePath + opt.theme + '/images/word.gif'
                  : opt.langPath + opt.lang + '/images/localimage.png') +
                ') no-repeat center center;border:1px solid #ddd',
            });
          }
        });
      },
    };
  });
  UE.plugin.register('autosave', function () {
    var me = this,
      saveKey = null;
    function save(editor) {
      var saveData;
      if (!editor.hasContents()) {
        saveKey && me.removePreferences(saveKey);
        return;
      }
      editor._autoSaveTimer = null;
      saveData = me.body.innerHTML;
      if (editor.fireEvent('beforeautosave', { content: saveData }) === false) {
        return;
      }
      me.setPreferences(saveKey, saveData);
      editor.fireEvent('afterautosave', { content: saveData });
    }
    return {
      defaultOptions: { autoSaveEnable: true, autoSaveRestore: false, autoSaveKey: null },
      bindEvents: {
        ready: function () {
          saveKey = me.getOpt('autoSaveKey');
          if (!saveKey) {
            var _suffix = '_DraftsData',
              key = null;
            if (me.key) {
              key = me.key + _suffix;
            } else {
              key = (me.container.parentNode.id || 'ue-common') + _suffix;
            }
            saveKey = (location.protocol + location.host + location.pathname).replace(/[.:\/]/g, '_') + key;
          }
          if (me.getOpt('autoSaveRestore')) {
            var data = me.getPreferences(saveKey);
            if (data) {
              me.body.innerHTML = data;
              me.fireEvent('showmessage', { type: 'info', content: me.getLang('autosave').autoRestoreTip });
            }
          }
        },
        beforesubmit: function () {
          if (!me.getOpt('autoSaveEnable') || !saveKey) {
            return;
          }
          me.execCommand('clear_auto_save_content');
        },
        contentchange: function () {
          if (!me.isReady) {
            return;
          }
          if (!me.getOpt('autoSaveEnable') || !saveKey) {
            return;
          }
          if (me._autoSaveTimer) {
            window.clearTimeout(me._autoSaveTimer);
          }
          me._autoSaveTimer = window.setTimeout(function () {
            save(me);
          }, 1e3);
        },
      },
      commands: {
        clear_auto_save_content: {
          execCommand: function (cmd, name) {
            if (saveKey && me.getPreferences(saveKey)) {
              me.removePreferences(saveKey);
            }
          },
          notNeedUndo: true,
          ignoreContentChange: true,
        },
        set_auto_save_content: {
          execCommand: function (cmd, name) {
            save(me);
          },
          notNeedUndo: true,
          ignoreContentChange: true,
        },
        get_auto_save_content: {
          execCommand: function (cmd, name) {
            return me.getPreferences(saveKey) || '';
          },
          notNeedUndo: true,
          ignoreContentChange: true,
        },
        auto_save_restore: {
          execCommand: function (cmd, name) {
            if (saveKey) {
              me.body.innerHTML = me.getPreferences(saveKey) || '<p>' + domUtils.fillHtml + '</p>';
              me.focus(true);
            }
          },
          queryCommandState: function () {
            return saveKey ? (me.getPreferences(saveKey) === null ? -1 : 0) : -1;
          },
          notNeedUndo: true,
          ignoreContentChange: true,
        },
      },
    };
  });
  UE.plugin.register('formula', function () {
    var me = this,
      images = [];
    return {
      commands: {
        formula: {
          execCommand: function (cmdName, value) {
            var range = me.selection.getRange(),
              img = range.getClosedNode();
            value = encodeURIComponent(value);
            var formulaConfig = me.getOpt('formulaConfig');
            var src = formulaConfig.imageUrlTemplate.replace(/\{\}/, value);
            if (img) {
              img.setAttribute('src', src);
            } else {
              me.execCommand('insertHtml', '<img src="' + src + '" data-formula-image="' + value + '" />');
            }
          },
        },
      },
    };
  });
  UE.plugins['dragdrop'] = function () {
    var me = this;
    me.ready(function () {
      domUtils.on(this.body, 'dragend', function () {
        var rng = me.selection.getRange();
        var node = rng.getClosedNode() || me.selection.getStart();
        if (node && node.tagName == 'IMG') {
          var pre = node.previousSibling,
            next;
          while ((next = node.nextSibling)) {
            if (next.nodeType == 1 && next.tagName == 'SPAN' && !next.firstChild) {
              domUtils.remove(next);
            } else {
              break;
            }
          }
          if (
            ((pre && pre.nodeType == 1 && !domUtils.isEmptyBlock(pre)) || !pre) &&
            (!next || (next && !domUtils.isEmptyBlock(next)))
          ) {
            if (pre && pre.tagName == 'P' && !domUtils.isEmptyBlock(pre)) {
              pre.appendChild(node);
              domUtils.moveChild(next, pre);
              domUtils.remove(next);
            } else if (next && next.tagName == 'P' && !domUtils.isEmptyBlock(next)) {
              next.insertBefore(node, next.firstChild);
            }
            if (pre && pre.tagName == 'P' && domUtils.isEmptyBlock(pre)) {
              domUtils.remove(pre);
            }
            if (next && next.tagName == 'P' && domUtils.isEmptyBlock(next)) {
              domUtils.remove(next);
            }
            rng.selectNode(node).select();
            me.fireEvent('saveScene');
          }
        }
      });
    });
    me.addListener('keyup', function (type, evt) {
      var keyCode = evt.keyCode || evt.which;
      if (keyCode == 13) {
        var rng = me.selection.getRange(),
          node;
        if ((node = domUtils.findParentByTagName(rng.startContainer, 'p', true))) {
          if (domUtils.getComputedStyle(node, 'text-align') == 'center') {
            domUtils.removeStyle(node, 'text-align');
          }
        }
      }
    });
  };
  UE.plugins['undo'] = function () {
    var saveSceneTimer;
    var me = this,
      maxUndoCount = me.options.maxUndoCount || 20,
      maxInputCount = me.options.maxInputCount || 20,
      fillchar = new RegExp(domUtils.fillChar + '|</hr>', 'gi');
    var noNeedFillCharTags = { ol: 1, ul: 1, table: 1, tbody: 1, tr: 1, body: 1 };
    var orgState = me.options.autoClearEmptyNode;
    function compareAddr(indexA, indexB) {
      if (indexA.length != indexB.length) return 0;
      for (var i = 0, l = indexA.length; i < l; i++) {
        if (indexA[i] != indexB[i]) return 0;
      }
      return 1;
    }
    function compareRangeAddress(rngAddrA, rngAddrB) {
      if (rngAddrA.collapsed != rngAddrB.collapsed) {
        return 0;
      }
      if (
        !compareAddr(rngAddrA.startAddress, rngAddrB.startAddress) ||
        !compareAddr(rngAddrA.endAddress, rngAddrB.endAddress)
      ) {
        return 0;
      }
      return 1;
    }
    function UndoManager() {
      this.list = [];
      this.index = 0;
      this.hasUndo = false;
      this.hasRedo = false;
      this.undo = function () {
        if (this.hasUndo) {
          if (!this.list[this.index - 1] && this.list.length == 1) {
            this.reset();
            return;
          }
          while (this.list[this.index].content == this.list[this.index - 1].content) {
            this.index--;
            if (this.index == 0) {
              return this.restore(0);
            }
          }
          this.restore(--this.index);
        }
      };
      this.redo = function () {
        if (this.hasRedo) {
          while (this.list[this.index].content == this.list[this.index + 1].content) {
            this.index++;
            if (this.index == this.list.length - 1) {
              return this.restore(this.index);
            }
          }
          this.restore(++this.index);
        }
      };
      this.restore = function () {
        var me = this.editor;
        var scene = this.list[this.index];
        var root = UE.htmlparser(scene.content.replace(fillchar, ''));
        me.options.autoClearEmptyNode = false;
        me.filterInputRule(root);
        me.options.autoClearEmptyNode = orgState;
        me.document.body.innerHTML = root.toHtml();
        me.fireEvent('afterscencerestore');
        if (browser.ie) {
          utils.each(domUtils.getElementsByTagName(me.document, 'td th caption p'), function (node) {
            if (domUtils.isEmptyNode(node)) {
              domUtils.fillNode(me.document, node);
            }
          });
        }
        try {
          var rng = new dom.Range(me.document).moveToAddress(scene.address);
          rng.select(noNeedFillCharTags[rng.startContainer.nodeName.toLowerCase()]);
        } catch (e) {}
        this.update();
        this.clearKey();
        me.fireEvent('reset', true);
      };
      this.getScene = function () {
        var me = this.editor;
        var rng = me.selection.getRange(),
          rngAddress = rng.createAddress(false, true);
        me.fireEvent('beforegetscene');
        var root = UE.htmlparser(me.body.innerHTML);
        me.options.autoClearEmptyNode = false;
        me.filterOutputRule(root);
        me.options.autoClearEmptyNode = orgState;
        var cont = root.toHtml();
        me.fireEvent('aftergetscene');
        return { address: rngAddress, content: cont };
      };
      this.save = function (notCompareRange, notSetCursor) {
        clearTimeout(saveSceneTimer);
        var currentScene = this.getScene(notSetCursor),
          lastScene = this.list[this.index];
        if (!lastScene || (lastScene && lastScene.content != currentScene.content)) {
          setTimeout(function () {
            me.trigger('contentchange');
          }, 0);
        }
        if (
          lastScene &&
          lastScene.content == currentScene.content &&
          (notCompareRange ? 1 : compareRangeAddress(lastScene.address, currentScene.address))
        ) {
          return;
        }
        this.list = this.list.slice(0, this.index + 1);
        this.list.push(currentScene);
        if (this.list.length > maxUndoCount) {
          this.list.shift();
        }
        this.index = this.list.length - 1;
        this.clearKey();
        this.update();
      };
      this.update = function () {
        this.hasRedo = !!this.list[this.index + 1];
        this.hasUndo = !!this.list[this.index - 1];
      };
      this.reset = function () {
        this.list = [];
        this.index = 0;
        this.hasUndo = false;
        this.hasRedo = false;
        this.clearKey();
      };
      this.clearKey = function () {
        keycont = 0;
        lastKeyCode = null;
      };
    }
    me.undoManger = new UndoManager();
    me.undoManger.editor = me;
    function saveScene() {
      this.undoManger.save();
    }
    me.addListener('saveScene', function () {
      var args = Array.prototype.splice.call(arguments, 1);
      this.undoManger.save.apply(this.undoManger, args);
    });
    me.addListener('reset', function (type, exclude) {
      if (!exclude) {
        this.undoManger.reset();
      }
    });
    me.commands['redo'] = me.commands['undo'] = {
      execCommand: function (cmdName) {
        this.undoManger[cmdName]();
      },
      queryCommandState: function (cmdName) {
        return this.undoManger['has' + (cmdName.toLowerCase() == 'undo' ? 'Undo' : 'Redo')] ? 0 : -1;
      },
      notNeedUndo: 1,
    };
    var keys = { 16: 1, 17: 1, 18: 1, 37: 1, 38: 1, 39: 1, 40: 1 },
      keycont = 0,
      lastKeyCode;
    var inputType = false;
    me.addListener('ready', function () {
      domUtils.on(this.body, 'compositionstart', function () {
        inputType = true;
      });
      domUtils.on(this.body, 'compositionend', function () {
        inputType = false;
      });
    });
    me.addshortcutkey({ Undo: 'ctrl+90', Redo: 'ctrl+89' });
    var isCollapsed = true;
    me.addListener('keyup', function (type, evt) {
      var me = this;
      var keyCode = evt.keyCode || evt.which;
      if (!keys[keyCode] && !evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey) {
        if (inputType) return;
        if (!me.selection.getRange().collapsed) {
          me.undoManger.save(false, true);
          isCollapsed = false;
          return;
        }
        if (me.undoManger.list.length === 0) {
          me.undoManger.save(true);
        }
        clearTimeout(saveSceneTimer);
        function save(cont) {
          cont.undoManger.save(false, true);
          cont.fireEvent('selectionchange');
        }
        saveSceneTimer = setTimeout(function () {
          if (inputType) {
            var intervalTimer = setInterval(function () {
              if (!inputType) {
                save(me);
                clearInterval(intervalTimer);
              }
            }, 300);
            return;
          }
          save(me);
        }, 200);
        lastKeyCode = keyCode;
        keycont++;
        if (keycont >= maxInputCount) {
          save(me);
        }
      }
    });
    me.addListener('keyup', function (type, evt) {
      var keyCode = evt.keyCode || evt.which;
      if (!keys[keyCode] && !evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey) {
        if (inputType) return;
        if (!isCollapsed) {
          this.undoManger.save(false, true);
          isCollapsed = true;
        }
      }
    });
    me.stopCmdUndo = function () {
      me.__hasEnterExecCommand = true;
    };
    me.startCmdUndo = function () {
      me.__hasEnterExecCommand = false;
    };
  };
  UE.plugin.register('copy', function () {
    var me = this;
    function initZeroClipboard() {
      ZeroClipboard.config({
        debug: false,
        swfPath: me.options.UEDITOR_HOME_URL + 'third-party/zeroclipboard/ZeroClipboard.swf',
      });
      var client = (me.zeroclipboard = new ZeroClipboard());
      client.on('copy', function (e) {
        var client = e.client,
          rng = me.selection.getRange(),
          div = document.createElement('div');
        div.appendChild(rng.cloneContents());
        client.setText(div.innerText || div.textContent);
        client.setHtml(div.innerHTML);
        rng.select();
      });
      client.on('mouseover mouseout', function (e) {
        var target = e.target;
        if (target) {
          if (e.type == 'mouseover') {
            domUtils.addClass(target, 'edui-state-hover');
          } else if (e.type == 'mouseout') {
            domUtils.removeClasses(target, 'edui-state-hover');
          }
        }
      });
      client.on('wrongflash noflash', function () {
        ZeroClipboard.destroy();
      });
      me.fireEvent('zeroclipboardready', client);
    }
    return {
      bindEvents: {
        ready: function () {
          if (!browser.ie) {
            if (window.ZeroClipboard) {
              initZeroClipboard();
            } else {
              utils.loadFile(
                document,
                {
                  src: me.options.UEDITOR_HOME_URL + 'third-party/zeroclipboard/ZeroClipboard.js',
                  tag: 'script',
                  type: 'text/javascript',
                  defer: 'defer',
                },
                function () {
                  initZeroClipboard();
                },
              );
            }
          }
        },
      },
      commands: {
        copy: {
          execCommand: function (cmd) {
            if (!me.document.execCommand('copy')) {
              alert(me.getLang('copymsg'));
            }
          },
        },
      },
    };
  });
  UE.plugins['paste'] = function () {
    function getClipboardData(callback) {
      var doc = this.document;
      if (doc.getElementById('baidu_pastebin')) {
        return;
      }
      var range = this.selection.getRange(),
        bk = range.createBookmark(),
        pastebin = doc.createElement('div');
      pastebin.id = 'baidu_pastebin';
      browser.webkit && pastebin.appendChild(doc.createTextNode(domUtils.fillChar + domUtils.fillChar));
      doc.body.appendChild(pastebin);
      bk.start.style.display = '';
      pastebin.style.cssText =
        'position:absolute;width:1px;height:1px;overflow:hidden;left:-1000px;white-space:nowrap;top:' +
        domUtils.getXY(bk.start).y +
        'px';
      range.selectNodeContents(pastebin).select(true);
      setTimeout(function () {
        if (browser.webkit) {
          for (var i = 0, pastebins = doc.querySelectorAll('#baidu_pastebin'), pi; (pi = pastebins[i++]); ) {
            if (domUtils.isEmptyNode(pi)) {
              domUtils.remove(pi);
            } else {
              pastebin = pi;
              break;
            }
          }
        }
        try {
          pastebin.parentNode.removeChild(pastebin);
        } catch (e) {}
        range.moveToBookmark(bk).select(true);
        callback(pastebin);
      }, 0);
    }
    var me = this;
    me.setOpt({ retainOnlyLabelPasted: false });
    var txtContent, htmlContent, address;
    function getPureHtml(html) {
      var result = html.replace(/<(\/?)([\w\-]+)([^>]*)>/gi, function (a, b, tagName, attrs) {
        tagName = tagName.toLowerCase();
        if ({ img: 1 }[tagName]) {
          return a;
        }
        attrs = attrs.replace(/([\w\-]*?)\s*=\s*(("([^"]*)")|('([^']*)')|([^\s>]+))/gi, function (str, atr, val) {
          if ({ src: 1, href: 1, name: 1 }[atr.toLowerCase()]) {
            return atr + '=' + val + ' ';
          }
          return '';
        });
        if ({ span: 1, div: 1 }[tagName]) {
          return '';
        } else {
          attrs = utils.trim(attrs);
          return '<' + b + tagName + (attrs ? ' ' + attrs : '') + '>';
        }
      });
      result = result.replace(/<\/p >/g, '</p>');
      return result;
    }
    function filter(div) {
      var html;
      if (div.firstChild) {
        var nodes = domUtils.getElementsByTagName(div, 'span');
        for (var i = 0, ni; (ni = nodes[i++]); ) {
          if (ni.id == '_baidu_cut_start' || ni.id == '_baidu_cut_end') {
            domUtils.remove(ni);
          }
        }
        if (browser.webkit) {
          var brs = div.querySelectorAll('div br');
          for (var i = 0, bi; (bi = brs[i++]); ) {
            var pN = bi.parentNode;
            if (pN.tagName == 'DIV' && pN.childNodes.length == 1) {
              pN.innerHTML = '<p><br/></p>';
              domUtils.remove(pN);
            }
          }
          var divs = div.querySelectorAll('#baidu_pastebin');
          for (var i = 0, di; (di = divs[i++]); ) {
            var tmpP = me.document.createElement('p');
            di.parentNode.insertBefore(tmpP, di);
            while (di.firstChild) {
              tmpP.appendChild(di.firstChild);
            }
            domUtils.remove(di);
          }
          var metas = div.querySelectorAll('meta');
          for (var i = 0, ci; (ci = metas[i++]); ) {
            domUtils.remove(ci);
          }
          var brs = div.querySelectorAll('br');
          for (i = 0; (ci = brs[i++]); ) {
            if (/^apple-/i.test(ci.className)) {
              domUtils.remove(ci);
            }
          }
        }
        if (browser.gecko) {
          var dirtyNodes = div.querySelectorAll('[_moz_dirty]');
          for (i = 0; (ci = dirtyNodes[i++]); ) {
            ci.removeAttribute('_moz_dirty');
          }
        }
        if (!browser.ie) {
          var spans = div.querySelectorAll('span.Apple-style-span');
          for (var i = 0, ci; (ci = spans[i++]); ) {
            domUtils.remove(ci, true);
          }
        }
        html = div.innerHTML;
        html = UE.filterWord(html);
        var root = UE.htmlparser(html);
        if (me.options.filterRules) {
          UE.filterNode(root, me.options.filterRules);
        }
        me.filterInputRule(root);
        if (browser.webkit) {
          var br = root.lastChild();
          if (br && br.type == 'element' && br.tagName == 'br') {
            root.removeChild(br);
          }
          utils.each(me.body.querySelectorAll('div'), function (node) {
            if (domUtils.isEmptyBlock(node)) {
              domUtils.remove(node, true);
            }
          });
        }
        html = { html: root.toHtml() };
        me.fireEvent('beforepaste', html, root);
        if (!html.html) {
          return;
        }
        root = UE.htmlparser(html.html, true);
        if (me.queryCommandState('pasteplain') === 1) {
          me.execCommand('insertHtml', UE.filterNode(root, me.options.filterTxtRules).toHtml(), true);
        } else {
          UE.filterNode(root, me.options.filterTxtRules);
          txtContent = root.toHtml();
          htmlContent = html.html;
          address = me.selection.getRange().createAddress(true);
          me.execCommand(
            'insertHtml',
            me.getOpt('retainOnlyLabelPasted') === true ? getPureHtml(htmlContent) : htmlContent,
            true,
          );
        }
        me.fireEvent('afterpaste', html);
      }
    }
    me.addListener('pasteTransfer', function (cmd, plainType) {
      if (address && txtContent && htmlContent && txtContent != htmlContent) {
        var range = me.selection.getRange();
        range.moveToAddress(address, true);
        if (!range.collapsed) {
          while (!domUtils.isBody(range.startContainer)) {
            var start = range.startContainer;
            if (start.nodeType == 1) {
              start = start.childNodes[range.startOffset];
              if (!start) {
                range.setStartBefore(range.startContainer);
                continue;
              }
              var pre = start.previousSibling;
              if (pre && pre.nodeType == 3 && new RegExp('^[\n\r\t ' + domUtils.fillChar + ']*$').test(pre.nodeValue)) {
                range.setStartBefore(pre);
              }
            }
            if (range.startOffset == 0) {
              range.setStartBefore(range.startContainer);
            } else {
              break;
            }
          }
          while (!domUtils.isBody(range.endContainer)) {
            var end = range.endContainer;
            if (end.nodeType == 1) {
              end = end.childNodes[range.endOffset];
              if (!end) {
                range.setEndAfter(range.endContainer);
                continue;
              }
              var next = end.nextSibling;
              if (
                next &&
                next.nodeType == 3 &&
                new RegExp('^[\n\r\t' + domUtils.fillChar + ']*$').test(next.nodeValue)
              ) {
                range.setEndAfter(next);
              }
            }
            if (
              range.endOffset ==
              range.endContainer[range.endContainer.nodeType == 3 ? 'nodeValue' : 'childNodes'].length
            ) {
              range.setEndAfter(range.endContainer);
            } else {
              break;
            }
          }
        }
        range.deleteContents();
        range.select(true);
        me.__hasEnterExecCommand = true;
        var html = htmlContent;
        if (plainType === 2) {
          html = getPureHtml(html);
        } else if (plainType) {
          html = txtContent;
        }
        me.execCommand('inserthtml', html, true);
        me.__hasEnterExecCommand = false;
        var rng = me.selection.getRange();
        while (
          !domUtils.isBody(rng.startContainer) &&
          !rng.startOffset &&
          rng.startContainer[rng.startContainer.nodeType == 3 ? 'nodeValue' : 'childNodes'].length
        ) {
          rng.setStartBefore(rng.startContainer);
        }
        var tmpAddress = rng.createAddress(true);
        address.endAddress = tmpAddress.startAddress;
      }
    });
    me.addListener('ready', function () {
      domUtils.on(me.body, 'cut', function () {
        var range = me.selection.getRange();
        if (!range.collapsed && me.undoManger) {
          me.undoManger.save();
        }
      });
      domUtils.on(me.body, browser.ie || browser.opera ? 'keydown' : 'paste', function (e) {
        if ((browser.ie || browser.opera) && ((!e.ctrlKey && !e.metaKey) || e.keyCode != '86')) {
          return;
        }
        getClipboardData.call(me, function (div) {
          filter(div);
        });
      });
    });
    me.commands['paste'] = {
      execCommand: function (cmd) {
        if (browser.ie) {
          getClipboardData.call(me, function (div) {
            filter(div);
          });
          me.document.execCommand('paste');
        } else {
          alert(me.getLang('pastemsg'));
        }
      },
    };
  };
  UE.plugins['pasteplain'] = function () {
    var me = this;
    me.setOpt({
      pasteplain: false,
      filterTxtRules: (function () {
        function transP(node) {
          node.tagName = 'p';
          node.setStyle();
        }
        function removeNode(node) {
          node.parentNode.removeChild(node, true);
        }
        return {
          '-': 'script style object iframe embed input select',
          p: { $: {} },
          br: { $: {} },
          div: function (node) {
            var tmpNode,
              p = UE.uNode.createElement('p');
            while ((tmpNode = node.firstChild())) {
              if (tmpNode.type == 'text' || !UE.dom.dtd.$block[tmpNode.tagName]) {
                p.appendChild(tmpNode);
              } else {
                if (p.firstChild()) {
                  node.parentNode.insertBefore(p, node);
                  p = UE.uNode.createElement('p');
                } else {
                  node.parentNode.insertBefore(tmpNode, node);
                }
              }
            }
            if (p.firstChild()) {
              node.parentNode.insertBefore(p, node);
            }
            node.parentNode.removeChild(node);
          },
          ol: removeNode,
          ul: removeNode,
          dl: removeNode,
          dt: removeNode,
          dd: removeNode,
          li: removeNode,
          caption: transP,
          th: transP,
          tr: transP,
          h1: transP,
          h2: transP,
          h3: transP,
          h4: transP,
          h5: transP,
          h6: transP,
          td: function (node) {
            var txt = !!node.innerText();
            if (txt) {
              node.parentNode.insertAfter(UE.uNode.createText(' &nbsp; &nbsp;'), node);
            }
            node.parentNode.removeChild(node, node.innerText());
          },
        };
      })(),
    });
    var pasteplain = me.options.pasteplain;
    me.commands['pasteplain'] = {
      queryCommandState: function () {
        return pasteplain ? 1 : 0;
      },
      execCommand: function () {
        pasteplain = !pasteplain | 0;
      },
      notNeedUndo: 1,
    };
  };
  UE.plugins['list'] = function () {
    var me = this,
      notExchange = { TD: 1, PRE: 1, BLOCKQUOTE: 1 };
    me.setOpt({
      autoTransWordToList: false,
      insertorderedlist: { decimal: '', 'lower-alpha': '', 'lower-roman': '', 'upper-alpha': '', 'upper-roman': '' },
      insertunorderedlist: { circle: '', disc: '', square: '' },
      listDefaultPaddingLeft: '30',
      listiconpath: 'http://bs.baidu.com/listicon/',
      maxListLevel: -1,
      disablePInList: false,
    });
    function listToArray(list) {
      var arr = [];
      for (var p in list) {
        arr.push(p);
      }
      return arr;
    }
    var listStyle = { OL: listToArray(me.options.insertorderedlist), UL: listToArray(me.options.insertunorderedlist) };
    var liiconpath = me.options.listiconpath;
    me.ready(function () {
      var customCss = [];
      customCss.push('.list-paddingleft-1{padding-left:0}');
      customCss.push('.list-paddingleft-2{padding-left:' + me.options.listDefaultPaddingLeft + 'px}');
      customCss.push('.list-paddingleft-3{padding-left:' + me.options.listDefaultPaddingLeft * 2 + 'px}');
      utils.cssRule(
        'list',
        'ol,ul{margin:0;pading:0;' + (browser.ie ? '' : 'width:95%') + '}li{clear:both;}' + customCss.join('\n'),
        me.document,
      );
    });
    me.ready(function () {
      domUtils.on(me.body, 'cut', function () {
        setTimeout(function () {
          var rng = me.selection.getRange(),
            li;
          if (!rng.collapsed) {
            if ((li = domUtils.findParentByTagName(rng.startContainer, 'li', true))) {
              if (!li.nextSibling && domUtils.isEmptyBlock(li)) {
                var pn = li.parentNode,
                  node;
                if ((node = pn.previousSibling)) {
                  domUtils.remove(pn);
                  rng.setStartAtLast(node).collapse(true);
                  rng.select(true);
                } else if ((node = pn.nextSibling)) {
                  domUtils.remove(pn);
                  rng.setStartAtFirst(node).collapse(true);
                  rng.select(true);
                } else {
                  var tmpNode = me.document.createElement('p');
                  domUtils.fillNode(me.document, tmpNode);
                  pn.parentNode.insertBefore(tmpNode, pn);
                  domUtils.remove(pn);
                  rng.setStart(tmpNode, 0).collapse(true);
                  rng.select(true);
                }
              }
            }
          }
        });
      });
    });
    function getStyle(node) {
      var cls = node.className;
      if (domUtils.hasClass(node, /custom_/)) {
        return cls.match(/custom_(\w+)/)[1];
      }
      return domUtils.getStyle(node, 'list-style-type');
    }
    me.addListener('beforepaste', function (type, html) {
      var me = this,
        rng = me.selection.getRange(),
        li;
      var root = UE.htmlparser(html.html, true);
      if ((li = domUtils.findParentByTagName(rng.startContainer, 'li', true))) {
        var list = li.parentNode,
          tagName = list.tagName === 'OL' ? 'ul' : 'ol';
        utils.each(root.getNodesByTagName(tagName), function (n) {
          n.tagName = list.tagName;
          n.setAttr();
          if (n.parentNode === root) {
            type = getStyle(list) || (list.tagName == 'OL' ? 'decimal' : 'disc');
          } else {
            var className = n.parentNode.getAttr('class');
            if (className && /custom_/.test(className)) {
              type = className.match(/custom_(\w+)/)[1];
            } else {
              type = n.parentNode.getStyle('list-style-type');
            }
            if (!type) {
              type = list.tagName === 'OL' ? 'decimal' : 'disc';
            }
          }
          var index = utils.indexOf(listStyle[list.tagName], type);
          if (n.parentNode !== root) index = index + 1 === listStyle[list.tagName].length ? 0 : index + 1;
          var currentStyle = listStyle[list.tagName][index];
          n.setStyle('list-style-type', currentStyle);
        });
      }
      html.html = root.toHtml();
    });
    me.getOpt('disablePInList') === true &&
      me.addOutputRule(function (root) {
        utils.each(root.getNodesByTagName('li'), function (li) {
          var newChildrens = [],
            index = 0;
          utils.each(li.children, function (n) {
            if (n.tagName == 'p') {
              var tmpNode;
              while ((tmpNode = n.children.pop())) {
                newChildrens.splice(index, 0, tmpNode);
                tmpNode.parentNode = li;
                lastNode = tmpNode;
              }
              tmpNode = newChildrens[newChildrens.length - 1];
              if (!tmpNode || tmpNode.type !== 'element' || tmpNode.tagName !== 'br') {
                var br = UE.uNode.createElement('br');
                br.parentNode = li;
                newChildrens.push(br);
              }
              index = newChildrens.length;
            }
          });
          if (newChildrens.length) {
            li.children = newChildrens;
          }
        });
      });
    me.addInputRule(function (root) {
      utils.each(root.getNodesByTagName('li'), function (li) {
        var tmpP = UE.uNode.createElement('p');
        for (var i = 0, ci; (ci = li.children[i]); ) {
          if (ci.type === 'text' || dtd.p[ci.tagName]) {
            tmpP.appendChild(ci);
          } else {
            if (tmpP.firstChild()) {
              li.insertBefore(tmpP, ci);
              tmpP = UE.uNode.createElement('p');
              i = i + 2;
            } else {
              i++;
            }
          }
        }
        if ((tmpP.firstChild() && !tmpP.parentNode) || !li.firstChild()) {
          li.appendChild(tmpP);
        }
        if (!tmpP.firstChild()) {
          tmpP.innerHTML(browser.ie ? '&nbsp;' : '<br/>');
        }
        var p = li.firstChild();
        var lastChild = p.lastChild();
        if (lastChild && lastChild.type === 'text' && /^\s*$/.test(lastChild.data)) {
          p.removeChild(lastChild);
        }
      });
      if (me.options.autoTransWordToList) {
        var orderlisttype = {
            num1: /^\d+\)/,
            decimal: /^\d+\./,
            'lower-alpha': /^[a-z]+\)/,
            'upper-alpha': /^[A-Z]+\./,
            cn: /^[\u4E00\u4E8C\u4E09\u56DB\u516d\u4e94\u4e03\u516b\u4e5d]+[\u3001]/,
            cn2: /^\([\u4E00\u4E8C\u4E09\u56DB\u516d\u4e94\u4e03\u516b\u4e5d]+\)/,
          },
          unorderlisttype = { square: 'n' };
        function checkListType(content, container) {
          var span = container.firstChild();
          if (
            span &&
            span.type === 'element' &&
            span.tagName === 'span' &&
            /Wingdings|Symbol/.test(span.getStyle('font-family'))
          ) {
            for (var p in unorderlisttype) {
              if (unorderlisttype[p] == span.data) {
                return p;
              }
            }
            return 'disc';
          }
          for (var p in orderlisttype) {
            if (orderlisttype[p].test(content)) {
              return p;
            }
          }
        }
        utils.each(root.getNodesByTagName('p'), function (node) {
          if (node.getAttr('class') !== 'MsoListParagraph') {
            return;
          }
          node.setStyle('margin', '');
          node.setStyle('margin-left', '');
          node.setAttr('class', '');
          function appendLi(list, p, type) {
            if (list.tagName === 'ol') {
              if (browser.ie) {
                var first = p.firstChild();
                if (
                  first.type === 'element' &&
                  first.tagName === 'span' &&
                  orderlisttype[type].test(first.innerText())
                ) {
                  p.removeChild(first);
                }
              } else {
                p.innerHTML(p.innerHTML().replace(orderlisttype[type], ''));
              }
            } else {
              p.removeChild(p.firstChild());
            }
            var li = UE.uNode.createElement('li');
            li.appendChild(p);
            list.appendChild(li);
          }
          var tmp = node,
            type,
            cacheNode = node;
          if (node.parentNode.tagName !== 'li' && (type = checkListType(node.innerText(), node))) {
            var list = UE.uNode.createElement(me.options.insertorderedlist.hasOwnProperty(type) ? 'ol' : 'ul');
            list.setStyle('list-style-type', type);
            while (node && node.parentNode.tagName !== 'li' && checkListType(node.innerText(), node)) {
              tmp = node.nextSibling();
              if (!tmp) {
                node.parentNode.insertBefore(list, node);
              }
              appendLi(list, node, type);
              node = tmp;
            }
            if (!list.parentNode && node && node.parentNode) {
              node.parentNode.insertBefore(list, node);
            }
          }
          var span = cacheNode.firstChild();
          if (span && span.type == 'element' && span.tagName == 'span' && /^\s*(&nbsp;)+\s*$/.test(span.innerText())) {
            span.parentNode.removeChild(span);
          }
        });
      }
    });
    me.addListener('contentchange', function () {
      adjustListStyle(me.document);
    });
    function adjustListStyle(doc, ignore) {
      utils.each(domUtils.getElementsByTagName(doc, 'ol ul'), function (node) {
        if (!domUtils.inDoc(node, doc)) return;
        var parent = node.parentNode;
        if (parent.tagName === node.tagName) {
          var nodeStyleType = getStyle(node) || (node.tagName === 'OL' ? 'decimal' : 'disc'),
            parentStyleType = getStyle(parent) || (parent.tagName === 'OL' ? 'decimal' : 'disc');
          if (nodeStyleType === parentStyleType) {
            var styleIndex = utils.indexOf(listStyle[node.tagName], nodeStyleType);
            styleIndex = styleIndex + 1 === listStyle[node.tagName].length ? 0 : styleIndex + 1;
            setListStyle(node, listStyle[node.tagName][styleIndex]);
          }
        }
        var index = 0,
          type = 2;
        if (domUtils.hasClass(node, /custom_/)) {
          if (!(/[ou]l/i.test(parent.tagName) && domUtils.hasClass(parent, /custom_/))) {
            type = 1;
          }
        } else {
          if (/[ou]l/i.test(parent.tagName) && domUtils.hasClass(parent, /custom_/)) {
            type = 3;
          }
        }
        var style = domUtils.getStyle(node, 'list-style-type');
        style && (node.style.cssText = 'list-style-type:' + style);
        node.className = utils.trim(node.className.replace(/list-paddingleft-\w+/, '')) + ' list-paddingleft-' + type;
        utils.each(domUtils.getElementsByTagName(node, 'li'), function (li) {
          li.style.cssText && (li.style.cssText = '');
          if (!li.firstChild) {
            domUtils.remove(li);
            return;
          }
          if (li.parentNode !== node) {
            return;
          }
          index++;
          if (domUtils.hasClass(node, /custom_/)) {
            var paddingLeft = 1,
              currentStyle = getStyle(node);
            if (node.tagName === 'OL') {
              if (currentStyle) {
                switch (currentStyle) {
                  case 'cn':
                  case 'cn1':
                  case 'cn2':
                    if (index > 10 && (index % 10 === 0 || (index > 10 && index < 20))) {
                      paddingLeft = 2;
                    } else if (index > 20) {
                      paddingLeft = 3;
                    }
                    break;
                  case 'num2':
                    if (index > 9) {
                      paddingLeft = 2;
                    }
                }
              }
              li.className = 'list-' + currentStyle + '-paddingleft-' + paddingLeft;
            } else {
              li.className = 'list-' + currentStyle + '-paddingleft';
            }
          } else {
            li.className = li.className.replace(/list-[\w\-]+/gi, '');
          }
          var className = li.getAttribute('class');
          if (className !== null && !className.replace(/\s/g, '')) {
            domUtils.removeAttributes(li, 'class');
          }
        });
        !ignore &&
          adjustList(
            node,
            node.tagName.toLowerCase(),
            getStyle(node) || domUtils.getStyle(node, 'list-style-type'),
            true,
          );
      });
    }
    function adjustList(list, tag, style, ignoreEmpty) {
      var nextList = list.nextSibling;
      if (
        nextList &&
        nextList.nodeType === 1 &&
        nextList.tagName.toLowerCase() === tag &&
        (getStyle(nextList) || domUtils.getStyle(nextList, 'list-style-type') || (tag == 'ol' ? 'decimal' : 'disc')) ==
          style
      ) {
        domUtils.moveChild(nextList, list);
        if (nextList.childNodes.length === 0) {
          domUtils.remove(nextList);
        }
      }
      if (nextList && domUtils.isFillChar(nextList)) {
        domUtils.remove(nextList);
      }
      var preList = list.previousSibling;
      if (
        preList &&
        preList.nodeType === 1 &&
        preList.tagName.toLowerCase() == tag &&
        (getStyle(preList) || domUtils.getStyle(preList, 'list-style-type') || (tag == 'ol' ? 'decimal' : 'disc')) ===
          style
      ) {
        domUtils.moveChild(list, preList);
      }
      if (preList && domUtils.isFillChar(preList)) {
        domUtils.remove(preList);
      }
      !ignoreEmpty && domUtils.isEmptyBlock(list) && domUtils.remove(list);
      if (getStyle(list)) {
        adjustListStyle(list.ownerDocument, true);
      }
    }
    function setListStyle(list, style) {
      try {
        domUtils.setStyle(list, 'list-style-type', style);
      } catch (e) {}
    }
    function clearEmptySibling(node) {
      var tmpNode = node.previousSibling;
      if (tmpNode && domUtils.isEmptyBlock(tmpNode)) {
        domUtils.remove(tmpNode);
      }
      tmpNode = node.nextSibling;
      if (tmpNode && domUtils.isEmptyBlock(tmpNode)) {
        domUtils.remove(tmpNode);
      }
    }
    me.addListener('keydown', function (type, evt) {
      function preventAndSave() {
        evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);
        me.fireEvent('contentchange');
        me.undoManger && me.undoManger.save();
      }
      function findList(node, filterFn) {
        while (node && !domUtils.isBody(node)) {
          if (filterFn(node)) {
            return null;
          }
          if (node.nodeType === 1 && /[ou]l/i.test(node.tagName)) {
            return node;
          }
          node = node.parentNode;
        }
        return null;
      }
      var keyCode = evt.keyCode || evt.which;
      if (keyCode === 13 && !evt.shiftKey) {
        var rng = me.selection.getRange(),
          parent = domUtils.findParent(
            rng.startContainer,
            function (node) {
              return domUtils.isBlockElm(node);
            },
            true,
          ),
          li = domUtils.findParentByTagName(rng.startContainer, 'li', true);
        if (parent && parent.tagName !== 'PRE' && !li) {
          var html = parent.innerHTML.replace(new RegExp(domUtils.fillChar, 'g'), '');
          if (/^\s*1\s*\.[^\d]/.test(html)) {
            parent.innerHTML = html.replace(/^\s*1\s*\./, '');
            rng.setStartAtLast(parent).collapse(true).select();
            me.__hasEnterExecCommand = true;
            me.execCommand('insertorderedlist');
            me.__hasEnterExecCommand = false;
          }
        }
        var range = me.selection.getRange(),
          start = findList(range.startContainer, function (node) {
            return node.tagName === 'TABLE';
          }),
          end = range.collapsed
            ? start
            : findList(range.endContainer, function (node) {
                return node.tagName === 'TABLE';
              });
        if (start && end && start === end) {
          if (!range.collapsed) {
            start = domUtils.findParentByTagName(range.startContainer, 'li', true);
            end = domUtils.findParentByTagName(range.endContainer, 'li', true);
            if (start && end && start === end) {
              range.deleteContents();
              li = domUtils.findParentByTagName(range.startContainer, 'li', true);
              if (li && domUtils.isEmptyBlock(li)) {
                pre = li.previousSibling;
                next = li.nextSibling;
                p = me.document.createElement('p');
                domUtils.fillNode(me.document, p);
                parentList = li.parentNode;
                if (pre && next) {
                  range.setStart(next, 0).collapse(true).select(true);
                  domUtils.remove(li);
                } else {
                  if ((!pre && !next) || !pre) {
                    parentList.parentNode.insertBefore(p, parentList);
                  } else {
                    li.parentNode.parentNode.insertBefore(p, parentList.nextSibling);
                  }
                  domUtils.remove(li);
                  if (!parentList.firstChild) {
                    domUtils.remove(parentList);
                  }
                  range.setStart(p, 0).setCursor();
                }
                preventAndSave();
                return;
              }
            } else {
              var tmpRange = range.cloneRange(),
                bk = tmpRange.collapse(false).createBookmark();
              range.deleteContents();
              tmpRange.moveToBookmark(bk);
              var li = domUtils.findParentByTagName(tmpRange.startContainer, 'li', true);
              clearEmptySibling(li);
              tmpRange.select();
              preventAndSave();
              return;
            }
          }
          li = domUtils.findParentByTagName(range.startContainer, 'li', true);
          if (li) {
            if (domUtils.isEmptyBlock(li)) {
              bk = range.createBookmark();
              var parentList = li.parentNode;
              if (li !== parentList.lastChild) {
                domUtils.breakParent(li, parentList);
                clearEmptySibling(li);
              } else {
                parentList.parentNode.insertBefore(li, parentList.nextSibling);
                if (domUtils.isEmptyNode(parentList)) {
                  domUtils.remove(parentList);
                }
              }
              if (!dtd.$list[li.parentNode.tagName]) {
                if (!domUtils.isBlockElm(li.firstChild)) {
                  p = me.document.createElement('p');
                  li.parentNode.insertBefore(p, li);
                  while (li.firstChild) {
                    p.appendChild(li.firstChild);
                  }
                  domUtils.remove(li);
                } else {
                  domUtils.remove(li, true);
                }
              }
              range.moveToBookmark(bk).select();
            } else {
              var first = li.firstChild;
              if (!first || !domUtils.isBlockElm(first)) {
                var p = me.document.createElement('p');
                !li.firstChild && domUtils.fillNode(me.document, p);
                while (li.firstChild) {
                  p.appendChild(li.firstChild);
                }
                li.appendChild(p);
                first = p;
              }
              var span = me.document.createElement('span');
              range.insertNode(span);
              domUtils.breakParent(span, li);
              var nextLi = span.nextSibling;
              first = nextLi.firstChild;
              if (!first) {
                p = me.document.createElement('p');
                domUtils.fillNode(me.document, p);
                nextLi.appendChild(p);
                first = p;
              }
              if (domUtils.isEmptyNode(first)) {
                first.innerHTML = '';
                domUtils.fillNode(me.document, first);
              }
              range.setStart(first, 0).collapse(true).shrinkBoundary().select();
              domUtils.remove(span);
              var pre = nextLi.previousSibling;
              if (pre && domUtils.isEmptyBlock(pre)) {
                pre.innerHTML = '<p></p>';
                domUtils.fillNode(me.document, pre.firstChild);
              }
            }
            preventAndSave();
          }
        }
      }
      if (keyCode === 8) {
        range = me.selection.getRange();
        if (range.collapsed && domUtils.isStartInblock(range)) {
          tmpRange = range.cloneRange().trimBoundary();
          li = domUtils.findParentByTagName(range.startContainer, 'li', true);
          if (li && domUtils.isStartInblock(tmpRange)) {
            start = domUtils.findParentByTagName(range.startContainer, 'p', true);
            if (start && start !== li.firstChild) {
              var parentList = domUtils.findParentByTagName(start, ['ol', 'ul']);
              domUtils.breakParent(start, parentList);
              clearEmptySibling(start);
              me.fireEvent('contentchange');
              range.setStart(start, 0).setCursor(false, true);
              me.fireEvent('saveScene');
              domUtils.preventDefault(evt);
              return;
            }
            if (li && (pre = li.previousSibling)) {
              if (keyCode === 46 && li.childNodes.length) {
                return;
              }
              if (dtd.$list[pre.tagName]) {
                pre = pre.lastChild;
              }
              me.undoManger && me.undoManger.save();
              first = li.firstChild;
              if (domUtils.isBlockElm(first)) {
                if (domUtils.isEmptyNode(first)) {
                  pre.appendChild(first);
                  range.setStart(first, 0).setCursor(false, true);
                  while (li.firstChild) {
                    pre.appendChild(li.firstChild);
                  }
                } else {
                  span = me.document.createElement('span');
                  range.insertNode(span);
                  if (domUtils.isEmptyBlock(pre)) {
                    pre.innerHTML = '';
                  }
                  domUtils.moveChild(li, pre);
                  range.setStartBefore(span).collapse(true).select(true);
                  domUtils.remove(span);
                }
              } else {
                if (domUtils.isEmptyNode(li)) {
                  var p = me.document.createElement('p');
                  pre.appendChild(p);
                  range.setStart(p, 0).setCursor();
                } else {
                  range.setEnd(pre, pre.childNodes.length).collapse().select(true);
                  while (li.firstChild) {
                    pre.appendChild(li.firstChild);
                  }
                }
              }
              domUtils.remove(li);
              me.fireEvent('contentchange');
              me.fireEvent('saveScene');
              domUtils.preventDefault(evt);
              return;
            }
            if (li && !li.previousSibling) {
              var parentList = li.parentNode;
              var bk = range.createBookmark();
              if (domUtils.isTagNode(parentList.parentNode, 'ol ul')) {
                parentList.parentNode.insertBefore(li, parentList);
                if (domUtils.isEmptyNode(parentList)) {
                  domUtils.remove(parentList);
                }
              } else {
                while (li.firstChild) {
                  parentList.parentNode.insertBefore(li.firstChild, parentList);
                }
                domUtils.remove(li);
                if (domUtils.isEmptyNode(parentList)) {
                  domUtils.remove(parentList);
                }
              }
              range.moveToBookmark(bk).setCursor(false, true);
              me.fireEvent('contentchange');
              me.fireEvent('saveScene');
              domUtils.preventDefault(evt);
              return;
            }
          }
        }
      }
    });
    me.addListener('keyup', function (type, evt) {
      var keyCode = evt.keyCode || evt.which;
      if (keyCode == 8) {
        var rng = me.selection.getRange(),
          list;
        if ((list = domUtils.findParentByTagName(rng.startContainer, ['ol', 'ul'], true))) {
          adjustList(
            list,
            list.tagName.toLowerCase(),
            getStyle(list) || domUtils.getComputedStyle(list, 'list-style-type'),
            true,
          );
        }
      }
    });
    me.addListener('tabkeydown', function () {
      var range = me.selection.getRange();
      function checkLevel(li) {
        if (me.options.maxListLevel != -1) {
          var level = li.parentNode,
            levelNum = 0;
          while (/[ou]l/i.test(level.tagName)) {
            levelNum++;
            level = level.parentNode;
          }
          if (levelNum >= me.options.maxListLevel) {
            return true;
          }
        }
      }
      var li = domUtils.findParentByTagName(range.startContainer, 'li', true);
      if (li) {
        var bk;
        if (range.collapsed) {
          if (checkLevel(li)) return true;
          var parentLi = li.parentNode,
            list = me.document.createElement(parentLi.tagName),
            index = utils.indexOf(
              listStyle[list.tagName],
              getStyle(parentLi) || domUtils.getComputedStyle(parentLi, 'list-style-type'),
            );
          index = index + 1 == listStyle[list.tagName].length ? 0 : index + 1;
          var currentStyle = listStyle[list.tagName][index];
          setListStyle(list, currentStyle);
          if (domUtils.isStartInblock(range)) {
            me.fireEvent('saveScene');
            bk = range.createBookmark();
            parentLi.insertBefore(list, li);
            list.appendChild(li);
            adjustList(list, list.tagName.toLowerCase(), currentStyle);
            me.fireEvent('contentchange');
            range.moveToBookmark(bk).select(true);
            return true;
          }
        } else {
          me.fireEvent('saveScene');
          bk = range.createBookmark();
          for (var i = 0, closeList, parents = domUtils.findParents(li), ci; (ci = parents[i++]); ) {
            if (domUtils.isTagNode(ci, 'ol ul')) {
              closeList = ci;
              break;
            }
          }
          var current = li;
          if (bk.end) {
            while (current && !(domUtils.getPosition(current, bk.end) & domUtils.POSITION_FOLLOWING)) {
              if (checkLevel(current)) {
                current = domUtils.getNextDomNode(current, false, null, function (node) {
                  return node !== closeList;
                });
                continue;
              }
              var parentLi = current.parentNode,
                list = me.document.createElement(parentLi.tagName),
                index = utils.indexOf(
                  listStyle[list.tagName],
                  getStyle(parentLi) || domUtils.getComputedStyle(parentLi, 'list-style-type'),
                );
              var currentIndex = index + 1 == listStyle[list.tagName].length ? 0 : index + 1;
              var currentStyle = listStyle[list.tagName][currentIndex];
              setListStyle(list, currentStyle);
              parentLi.insertBefore(list, current);
              while (current && !(domUtils.getPosition(current, bk.end) & domUtils.POSITION_FOLLOWING)) {
                li = current.nextSibling;
                list.appendChild(current);
                if (!li || domUtils.isTagNode(li, 'ol ul')) {
                  if (li) {
                    while ((li = li.firstChild)) {
                      if (li.tagName == 'LI') {
                        break;
                      }
                    }
                  } else {
                    li = domUtils.getNextDomNode(current, false, null, function (node) {
                      return node !== closeList;
                    });
                  }
                  break;
                }
                current = li;
              }
              adjustList(list, list.tagName.toLowerCase(), currentStyle);
              current = li;
            }
          }
          me.fireEvent('contentchange');
          range.moveToBookmark(bk).select();
          return true;
        }
      }
    });
    function getLi(start) {
      while (start && !domUtils.isBody(start)) {
        if (start.nodeName == 'TABLE') {
          return null;
        }
        if (start.nodeName == 'LI') {
          return start;
        }
        start = start.parentNode;
      }
    }
    me.commands['insertorderedlist'] = me.commands['insertunorderedlist'] = {
      execCommand: function (command, style) {
        if (!style) {
          style = command.toLowerCase() == 'insertorderedlist' ? 'decimal' : 'disc';
        }
        var me = this,
          range = this.selection.getRange(),
          filterFn = function (node) {
            return node.nodeType == 1 ? node.tagName.toLowerCase() != 'br' : !domUtils.isWhitespace(node);
          },
          tag = command.toLowerCase() == 'insertorderedlist' ? 'ol' : 'ul',
          frag = me.document.createDocumentFragment();
        range.adjustmentBoundary().shrinkBoundary();
        var bko = range.createBookmark(true),
          start = getLi(me.document.getElementById(bko.start)),
          modifyStart = 0,
          end = getLi(me.document.getElementById(bko.end)),
          modifyEnd = 0,
          startParent,
          endParent,
          list,
          tmp;
        if (start || end) {
          start && (startParent = start.parentNode);
          if (!bko.end) {
            end = start;
          }
          end && (endParent = end.parentNode);
          if (startParent === endParent) {
            while (start !== end) {
              tmp = start;
              start = start.nextSibling;
              if (!domUtils.isBlockElm(tmp.firstChild)) {
                var p = me.document.createElement('p');
                while (tmp.firstChild) {
                  p.appendChild(tmp.firstChild);
                }
                tmp.appendChild(p);
              }
              frag.appendChild(tmp);
            }
            tmp = me.document.createElement('span');
            startParent.insertBefore(tmp, end);
            if (!domUtils.isBlockElm(end.firstChild)) {
              p = me.document.createElement('p');
              while (end.firstChild) {
                p.appendChild(end.firstChild);
              }
              end.appendChild(p);
            }
            frag.appendChild(end);
            domUtils.breakParent(tmp, startParent);
            if (domUtils.isEmptyNode(tmp.previousSibling)) {
              domUtils.remove(tmp.previousSibling);
            }
            if (domUtils.isEmptyNode(tmp.nextSibling)) {
              domUtils.remove(tmp.nextSibling);
            }
            var nodeStyle =
              getStyle(startParent) ||
              domUtils.getComputedStyle(startParent, 'list-style-type') ||
              (command.toLowerCase() == 'insertorderedlist' ? 'decimal' : 'disc');
            if (startParent.tagName.toLowerCase() == tag && nodeStyle == style) {
              for (var i = 0, ci, tmpFrag = me.document.createDocumentFragment(); (ci = frag.firstChild); ) {
                if (domUtils.isTagNode(ci, 'ol ul')) {
                  tmpFrag.appendChild(ci);
                } else {
                  while (ci.firstChild) {
                    tmpFrag.appendChild(ci.firstChild);
                    domUtils.remove(ci);
                  }
                }
              }
              tmp.parentNode.insertBefore(tmpFrag, tmp);
            } else {
              list = me.document.createElement(tag);
              setListStyle(list, style);
              list.appendChild(frag);
              tmp.parentNode.insertBefore(list, tmp);
            }
            domUtils.remove(tmp);
            list && adjustList(list, tag, style);
            range.moveToBookmark(bko).select();
            return;
          }
          if (start) {
            while (start) {
              tmp = start.nextSibling;
              if (domUtils.isTagNode(start, 'ol ul')) {
                frag.appendChild(start);
              } else {
                var tmpfrag = me.document.createDocumentFragment(),
                  hasBlock = 0;
                while (start.firstChild) {
                  if (domUtils.isBlockElm(start.firstChild)) {
                    hasBlock = 1;
                  }
                  tmpfrag.appendChild(start.firstChild);
                }
                if (!hasBlock) {
                  var tmpP = me.document.createElement('p');
                  tmpP.appendChild(tmpfrag);
                  frag.appendChild(tmpP);
                } else {
                  frag.appendChild(tmpfrag);
                }
                domUtils.remove(start);
              }
              start = tmp;
            }
            startParent.parentNode.insertBefore(frag, startParent.nextSibling);
            if (domUtils.isEmptyNode(startParent)) {
              range.setStartBefore(startParent);
              domUtils.remove(startParent);
            } else {
              range.setStartAfter(startParent);
            }
            modifyStart = 1;
          }
          if (end && domUtils.inDoc(endParent, me.document)) {
            start = endParent.firstChild;
            while (start && start !== end) {
              tmp = start.nextSibling;
              if (domUtils.isTagNode(start, 'ol ul')) {
                frag.appendChild(start);
              } else {
                tmpfrag = me.document.createDocumentFragment();
                hasBlock = 0;
                while (start.firstChild) {
                  if (domUtils.isBlockElm(start.firstChild)) {
                    hasBlock = 1;
                  }
                  tmpfrag.appendChild(start.firstChild);
                }
                if (!hasBlock) {
                  tmpP = me.document.createElement('p');
                  tmpP.appendChild(tmpfrag);
                  frag.appendChild(tmpP);
                } else {
                  frag.appendChild(tmpfrag);
                }
                domUtils.remove(start);
              }
              start = tmp;
            }
            var tmpDiv = domUtils.createElement(me.document, 'div', { tmpDiv: 1 });
            domUtils.moveChild(end, tmpDiv);
            frag.appendChild(tmpDiv);
            domUtils.remove(end);
            endParent.parentNode.insertBefore(frag, endParent);
            range.setEndBefore(endParent);
            if (domUtils.isEmptyNode(endParent)) {
              domUtils.remove(endParent);
            }
            modifyEnd = 1;
          }
        }
        if (!modifyStart) {
          range.setStartBefore(me.document.getElementById(bko.start));
        }
        if (bko.end && !modifyEnd) {
          range.setEndAfter(me.document.getElementById(bko.end));
        }
        range.enlarge(true, function (node) {
          return notExchange[node.tagName];
        });
        frag = me.document.createDocumentFragment();
        var bk = range.createBookmark(),
          current = domUtils.getNextDomNode(bk.start, false, filterFn),
          tmpRange = range.cloneRange(),
          tmpNode,
          block = domUtils.isBlockElm;
        while (current && current !== bk.end && domUtils.getPosition(current, bk.end) & domUtils.POSITION_PRECEDING) {
          if (current.nodeType == 3 || dtd.li[current.tagName]) {
            if (current.nodeType == 1 && dtd.$list[current.tagName]) {
              while (current.firstChild) {
                frag.appendChild(current.firstChild);
              }
              tmpNode = domUtils.getNextDomNode(current, false, filterFn);
              domUtils.remove(current);
              current = tmpNode;
              continue;
            }
            tmpNode = current;
            tmpRange.setStartBefore(current);
            while (current && current !== bk.end && (!block(current) || domUtils.isBookmarkNode(current))) {
              tmpNode = current;
              current = domUtils.getNextDomNode(current, false, null, function (node) {
                return !notExchange[node.tagName];
              });
            }
            if (current && block(current)) {
              tmp = domUtils.getNextDomNode(tmpNode, false, filterFn);
              if (tmp && domUtils.isBookmarkNode(tmp)) {
                current = domUtils.getNextDomNode(tmp, false, filterFn);
                tmpNode = tmp;
              }
            }
            tmpRange.setEndAfter(tmpNode);
            current = domUtils.getNextDomNode(tmpNode, false, filterFn);
            var li = range.document.createElement('li');
            li.appendChild(tmpRange.extractContents());
            if (domUtils.isEmptyNode(li)) {
              var tmpNode = range.document.createElement('p');
              while (li.firstChild) {
                tmpNode.appendChild(li.firstChild);
              }
              li.appendChild(tmpNode);
            }
            frag.appendChild(li);
          } else {
            current = domUtils.getNextDomNode(current, true, filterFn);
          }
        }
        range.moveToBookmark(bk).collapse(true);
        list = me.document.createElement(tag);
        setListStyle(list, style);
        list.appendChild(frag);
        range.insertNode(list);
        adjustList(list, tag, style);
        for (var i = 0, ci, tmpDivs = domUtils.getElementsByTagName(list, 'div'); (ci = tmpDivs[i++]); ) {
          if (ci.getAttribute('tmpDiv')) {
            domUtils.remove(ci, true);
          }
        }
        range.moveToBookmark(bko).select();
      },
      queryCommandState: function (command) {
        var tag = command.toLowerCase() == 'insertorderedlist' ? 'ol' : 'ul';
        var path = this.selection.getStartElementPath();
        for (var i = 0, ci; (ci = path[i++]); ) {
          if (ci.nodeName == 'TABLE') {
            return 0;
          }
          if (tag == ci.nodeName.toLowerCase()) {
            return 1;
          }
        }
        return 0;
      },
      queryCommandValue: function (command) {
        var tag = command.toLowerCase() == 'insertorderedlist' ? 'ol' : 'ul';
        var path = this.selection.getStartElementPath(),
          node;
        for (var i = 0, ci; (ci = path[i++]); ) {
          if (ci.nodeName == 'TABLE') {
            node = null;
            break;
          }
          if (tag == ci.nodeName.toLowerCase()) {
            node = ci;
            break;
          }
        }
        return node ? getStyle(node) || domUtils.getComputedStyle(node, 'list-style-type') : null;
      },
    };
  };
  (function () {
    var sourceEditors = {
      textarea: function (editor, holder) {
        var textarea = holder.ownerDocument.createElement('textarea');
        textarea.style.cssText =
          'position:absolute;resize:none;width:100%;height:100%;border:0;padding:0;margin:0;overflow-y:auto;';
        if (browser.ie && browser.version < 8) {
          textarea.style.width = holder.offsetWidth + 'px';
          textarea.style.height = holder.offsetHeight + 'px';
          holder.onresize = function () {
            textarea.style.width = holder.offsetWidth + 'px';
            textarea.style.height = holder.offsetHeight + 'px';
          };
        }
        holder.appendChild(textarea);
        return {
          setContent: function (content) {
            textarea.value = content;
          },
          getContent: function () {
            return textarea.value;
          },
          select: function () {
            var range;
            if (browser.ie) {
              range = textarea.createTextRange();
              range.collapse(true);
              range.select();
            } else {
              textarea.setSelectionRange(0, 0);
              textarea.focus();
            }
          },
          dispose: function () {
            holder.removeChild(textarea);
            holder.onresize = null;
            textarea = null;
            holder = null;
          },
          focus: function () {
            textarea.focus();
          },
          blur: function () {
            textarea.blur();
          },
        };
      },
      codemirror: function (editor, holder) {
        var codeEditor = window.CodeMirror(holder, {
          mode: 'text/html',
          tabMode: 'indent',
          lineNumbers: true,
          lineWrapping: true,
          onChange: function (v) {
            editor.sync();
            editor.fireEvent('contentchange');
          },
        });
        var dom = codeEditor.getWrapperElement();
        dom.style.cssText =
          'position:absolute;left:0;top:0;width:100%;height:100%;font-family:consolas,"Courier new",monospace;font-size:13px;';
        codeEditor.getScrollerElement().style.cssText = 'position:absolute;left:0;top:0;width:100%;height:100%;';
        codeEditor.refresh();
        return {
          getCodeMirror: function () {
            return codeEditor;
          },
          setContent: function (content) {
            codeEditor.setValue(content);
          },
          getContent: function () {
            return codeEditor.getValue();
          },
          select: function () {
            codeEditor.focus();
          },
          dispose: function () {
            holder.removeChild(dom);
            dom = null;
            codeEditor = null;
          },
          focus: function () {
            codeEditor.focus();
          },
          blur: function () {
            codeEditor.setOption('readOnly', true);
            codeEditor.setOption('readOnly', false);
          },
        };
      },
    };
    UE.plugins['source'] = function () {
      var me = this;
      var opt = this.options;
      var sourceMode = false;
      var sourceEditor;
      var orgSetContent;
      var orgFocus;
      var orgBlur;
      opt.sourceEditor = browser.ie ? 'textarea' : opt.sourceEditor || 'codemirror';
      me.setOpt({ sourceEditorFirst: false });
      function createSourceEditor(holder) {
        return sourceEditors[opt.sourceEditor == 'codemirror' && window.CodeMirror ? 'codemirror' : 'textarea'](
          me,
          holder,
        );
      }
      var bakCssText;
      var oldGetContent, bakAddress;
      me.commands['source'] = {
        execCommand: function () {
          sourceMode = !sourceMode;
          if (sourceMode) {
            bakAddress = me.selection.getRange().createAddress(false, true);
            me.undoManger && me.undoManger.save(true);
            if (browser.gecko) {
              me.body.contentEditable = false;
            }
            bakCssText = me.iframe.style.cssText;
            me.iframe.style.cssText += 'position:absolute;left:-32768px;top:-32768px;';
            me.fireEvent('beforegetcontent');
            var root = UE.htmlparser(me.body.innerHTML);
            me.filterOutputRule(root);
            root.traversal(function (node) {
              if (node.type == 'element') {
                switch (node.tagName) {
                  case 'td':
                  case 'th':
                  case 'caption':
                    if (node.children && node.children.length == 1) {
                      if (node.firstChild().tagName == 'br') {
                        node.removeChild(node.firstChild());
                      }
                    }
                    break;
                  case 'pre':
                    node.innerText(node.innerText().replace(/&nbsp;/g, ' '));
                }
              }
            });
            me.fireEvent('aftergetcontent');
            var content = root.toHtml(true);
            sourceEditor = createSourceEditor(me.iframe.parentNode);
            sourceEditor.setContent(content);
            orgSetContent = me.setContent;
            me.setContent = function (html) {
              var root = UE.htmlparser(html);
              me.filterInputRule(root);
              html = root.toHtml();
              sourceEditor.setContent(html);
            };
            setTimeout(function () {
              sourceEditor.select();
              me.addListener('fullscreenchanged', function () {
                try {
                  sourceEditor.getCodeMirror().refresh();
                } catch (e) {}
              });
            });
            oldGetContent = me.getContent;
            me.getContent = function () {
              return sourceEditor.getContent() || '<p>' + (browser.ie ? '' : '<br/>') + '</p>';
            };
            orgFocus = me.focus;
            orgBlur = me.blur;
            me.focus = function () {
              sourceEditor.focus();
            };
            me.blur = function () {
              orgBlur.call(me);
              sourceEditor.blur();
            };
          } else {
            me.iframe.style.cssText = bakCssText;
            var cont = sourceEditor.getContent() || '<p>' + (browser.ie ? '' : '<br/>') + '</p>';
            cont = cont.replace(new RegExp('[\\r\\t\\n ]*</?(\\w+)\\s*(?:[^>]*)>', 'g'), function (a, b) {
              if (b && !dtd.$inlineWithA[b.toLowerCase()]) {
                return a.replace(/(^[\n\r\t ]*)|([\n\r\t ]*$)/g, '');
              }
              return a.replace(/(^[\n\r\t]*)|([\n\r\t]*$)/g, '');
            });
            me.setContent = orgSetContent;
            me.setContent(cont);
            sourceEditor.dispose();
            sourceEditor = null;
            me.getContent = oldGetContent;
            me.focus = orgFocus;
            me.blur = orgBlur;
            var first = me.body.firstChild;
            if (!first) {
              me.body.innerHTML = '<p>' + (browser.ie ? '' : '<br/>') + '</p>';
              first = me.body.firstChild;
            }
            me.undoManger && me.undoManger.save(true);
            if (browser.gecko) {
              var input = document.createElement('input');
              input.style.cssText = 'position:absolute;left:0;top:-32768px';
              document.body.appendChild(input);
              me.body.contentEditable = false;
              setTimeout(function () {
                domUtils.setViewportOffset(input, { left: -32768, top: 0 });
                input.focus();
                setTimeout(function () {
                  me.body.contentEditable = true;
                  me.selection.getRange().moveToAddress(bakAddress).select(true);
                  domUtils.remove(input);
                });
              });
            } else {
              try {
                me.selection.getRange().moveToAddress(bakAddress).select(true);
              } catch (e) {}
            }
          }
          this.fireEvent('sourcemodechanged', sourceMode);
        },
        queryCommandState: function () {
          return sourceMode | 0;
        },
        notNeedUndo: 1,
      };
      var oldQueryCommandState = me.queryCommandState;
      me.queryCommandState = function (cmdName) {
        cmdName = cmdName.toLowerCase();
        if (sourceMode) {
          return cmdName in { source: 1, fullscreen: 1 } ? 1 : -1;
        }
        return oldQueryCommandState.apply(this, arguments);
      };
      if (opt.sourceEditor == 'codemirror') {
        me.addListener('ready', function () {
          utils.loadFile(
            document,
            {
              src: opt.codeMirrorJsUrl || opt.UEDITOR_HOME_URL + 'third-party/codemirror/codemirror.js',
              tag: 'script',
              type: 'text/javascript',
              defer: 'defer',
            },
            function () {
              if (opt.sourceEditorFirst) {
                setTimeout(function () {
                  me.execCommand('source');
                }, 0);
              }
            },
          );
          utils.loadFile(document, {
            tag: 'link',
            rel: 'stylesheet',
            type: 'text/css',
            href: opt.codeMirrorCssUrl || opt.UEDITOR_HOME_URL + 'third-party/codemirror/codemirror.css?221123',
          });
        });
      }
    };
  })();
  UE.plugins['enterkey'] = function () {
    var hTag,
      me = this,
      tag = me.options.enterTag;
    me.addListener('keyup', function (type, evt) {
      var keyCode = evt.keyCode || evt.which;
      if (keyCode == 13) {
        var range = me.selection.getRange(),
          start = range.startContainer,
          doSave;
        if (!browser.ie) {
          if (/h\d/i.test(hTag)) {
            if (browser.gecko) {
              var h = domUtils.findParentByTagName(
                start,
                ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'caption', 'table'],
                true,
              );
              if (!h) {
                me.document.execCommand('formatBlock', false, '<p>');
                doSave = 1;
              }
            } else {
              if (start.nodeType == 1) {
                var tmp = me.document.createTextNode(''),
                  div;
                range.insertNode(tmp);
                div = domUtils.findParentByTagName(tmp, 'div', true);
                if (div) {
                  var p = me.document.createElement('p');
                  while (div.firstChild) {
                    p.appendChild(div.firstChild);
                  }
                  div.parentNode.insertBefore(p, div);
                  domUtils.remove(div);
                  range.setStartBefore(tmp).setCursor();
                  doSave = 1;
                }
                domUtils.remove(tmp);
              }
            }
            if (me.undoManger && doSave) {
              me.undoManger.save();
            }
          }
          browser.opera && range.select();
        } else {
          me.fireEvent('saveScene', true, true);
        }
      }
    });
    me.addListener('keydown', function (type, evt) {
      var keyCode = evt.keyCode || evt.which;
      if (keyCode == 13) {
        if (me.fireEvent('beforeenterkeydown')) {
          domUtils.preventDefault(evt);
          return;
        }
        me.fireEvent('saveScene', true, true);
        hTag = '';
        var range = me.selection.getRange();
        if (!range.collapsed) {
          var start = range.startContainer,
            end = range.endContainer,
            startTd = domUtils.findParentByTagName(start, 'td', true),
            endTd = domUtils.findParentByTagName(end, 'td', true);
          if ((startTd && endTd && startTd !== endTd) || (!startTd && endTd) || (startTd && !endTd)) {
            evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);
            return;
          }
        }
        if (tag == 'p') {
          if (!browser.ie) {
            start = domUtils.findParentByTagName(
              range.startContainer,
              ['ol', 'ul', 'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'caption'],
              true,
            );
            if (!start && !browser.opera) {
              me.document.execCommand('formatBlock', false, '<p>');
              if (browser.gecko) {
                range = me.selection.getRange();
                start = domUtils.findParentByTagName(range.startContainer, 'p', true);
                start && domUtils.removeDirtyAttr(start);
              }
            } else {
              hTag = start.tagName;
              start.tagName.toLowerCase() == 'p' && browser.gecko && domUtils.removeDirtyAttr(start);
            }
          }
        } else {
          evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);
          if (!range.collapsed) {
            range.deleteContents();
            start = range.startContainer;
            if (start.nodeType == 1 && (start = start.childNodes[range.startOffset])) {
              while (start.nodeType == 1) {
                if (dtd.$empty[start.tagName]) {
                  range.setStartBefore(start).setCursor();
                  if (me.undoManger) {
                    me.undoManger.save();
                  }
                  return false;
                }
                if (!start.firstChild) {
                  var br = range.document.createElement('br');
                  start.appendChild(br);
                  range.setStart(start, 0).setCursor();
                  if (me.undoManger) {
                    me.undoManger.save();
                  }
                  return false;
                }
                start = start.firstChild;
              }
              if (start === range.startContainer.childNodes[range.startOffset]) {
                br = range.document.createElement('br');
                range.insertNode(br).setCursor();
              } else {
                range.setStart(start, 0).setCursor();
              }
            } else {
              br = range.document.createElement('br');
              range.insertNode(br).setStartAfter(br).setCursor();
            }
          } else {
            br = range.document.createElement('br');
            range.insertNode(br);
            var parent = br.parentNode;
            if (parent.lastChild === br) {
              br.parentNode.insertBefore(br.cloneNode(true), br);
              range.setStartBefore(br);
            } else {
              range.setStartAfter(br);
            }
            range.setCursor();
          }
        }
      }
    });
  };
  UE.plugins['keystrokes'] = function () {
    var me = this;
    var collapsed = true;
    me.addListener('keydown', function (type, evt) {
      var keyCode = evt.keyCode || evt.which,
        rng = me.selection.getRange();
      if (
        !rng.collapsed &&
        !(evt.ctrlKey || evt.shiftKey || evt.altKey || evt.metaKey) &&
        ((keyCode >= 65 && keyCode <= 90) ||
          (keyCode >= 48 && keyCode <= 57) ||
          (keyCode >= 96 && keyCode <= 111) ||
          { 13: 1, 8: 1, 46: 1 }[keyCode])
      ) {
        var tmpNode = rng.startContainer;
        if (domUtils.isFillChar(tmpNode)) {
          rng.setStartBefore(tmpNode);
        }
        tmpNode = rng.endContainer;
        if (domUtils.isFillChar(tmpNode)) {
          rng.setEndAfter(tmpNode);
        }
        rng.txtToElmBoundary();
        if (rng.endContainer && rng.endContainer.nodeType == 1) {
          tmpNode = rng.endContainer.childNodes[rng.endOffset];
          if (tmpNode && domUtils.isBr(tmpNode)) {
            rng.setEndAfter(tmpNode);
          }
        }
        if (rng.startOffset == 0) {
          tmpNode = rng.startContainer;
          if (domUtils.isBoundaryNode(tmpNode, 'firstChild')) {
            tmpNode = rng.endContainer;
            if (
              rng.endOffset == (tmpNode.nodeType == 3 ? tmpNode.nodeValue.length : tmpNode.childNodes.length) &&
              domUtils.isBoundaryNode(tmpNode, 'lastChild')
            ) {
              me.fireEvent('saveScene');
              me.body.innerHTML = '<p>' + (browser.ie ? '' : '<br/>') + '</p>';
              rng.setStart(me.body.firstChild, 0).setCursor(false, true);
              me._selectionChange();
              return;
            }
          }
        }
      }
      if (keyCode == keymap.Backspace) {
        rng = me.selection.getRange();
        collapsed = rng.collapsed;
        if (me.fireEvent('delkeydown', evt)) {
          return;
        }
        var start, end;
        if (rng.collapsed && rng.inFillChar()) {
          start = rng.startContainer;
          if (domUtils.isFillChar(start)) {
            rng.setStartBefore(start).shrinkBoundary(true).collapse(true);
            domUtils.remove(start);
          } else {
            start.nodeValue = start.nodeValue.replace(new RegExp('^' + domUtils.fillChar), '');
            rng.startOffset--;
            rng.collapse(true).select(true);
          }
        }
        if ((start = rng.getClosedNode())) {
          me.fireEvent('saveScene');
          rng.setStartBefore(start);
          domUtils.remove(start);
          rng.setCursor();
          me.fireEvent('saveScene');
          domUtils.preventDefault(evt);
          return;
        }
        if (!browser.ie) {
          start = domUtils.findParentByTagName(rng.startContainer, 'table', true);
          end = domUtils.findParentByTagName(rng.endContainer, 'table', true);
          if ((start && !end) || (!start && end) || start !== end) {
            evt.preventDefault();
            return;
          }
        }
      }
      if (keyCode == keymap.Tab) {
        var excludeTagNameForTabKey = { ol: 1, ul: 1, table: 1 };
        if (me.fireEvent('tabkeydown', evt)) {
          domUtils.preventDefault(evt);
          return;
        }
        var range = me.selection.getRange();
        me.fireEvent('saveScene');
        for (
          var i = 0, txt = '', tabSize = me.options.tabSize || 4, tabNode = me.options.tabNode || '&nbsp;';
          i < tabSize;
          i++
        ) {
          txt += tabNode;
        }
        var span = me.document.createElement('span');
        span.innerHTML = txt + domUtils.fillChar;
        if (range.collapsed) {
          range.insertNode(span.cloneNode(true).firstChild).setCursor(true);
        } else {
          var filterFn = function (node) {
            return domUtils.isBlockElm(node) && !excludeTagNameForTabKey[node.tagName.toLowerCase()];
          };
          start = domUtils.findParent(range.startContainer, filterFn, true);
          end = domUtils.findParent(range.endContainer, filterFn, true);
          if (start && end && start === end) {
            range.deleteContents();
            range.insertNode(span.cloneNode(true).firstChild).setCursor(true);
          } else {
            var bookmark = range.createBookmark();
            range.enlarge(true);
            var bookmark2 = range.createBookmark(),
              current = domUtils.getNextDomNode(bookmark2.start, false, filterFn);
            while (current && !(domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)) {
              current.insertBefore(span.cloneNode(true).firstChild, current.firstChild);
              current = domUtils.getNextDomNode(current, false, filterFn);
            }
            range.moveToBookmark(bookmark2).moveToBookmark(bookmark).select();
          }
        }
        domUtils.preventDefault(evt);
      }
      if (browser.gecko && keyCode == 46) {
        range = me.selection.getRange();
        if (range.collapsed) {
          start = range.startContainer;
          if (domUtils.isEmptyBlock(start)) {
            var parent = start.parentNode;
            while (domUtils.getChildCount(parent) == 1 && !domUtils.isBody(parent)) {
              start = parent;
              parent = parent.parentNode;
            }
            if (start === parent.lastChild) evt.preventDefault();
            return;
          }
        }
      }
      browser.chrome &&
        me.on('keydown', function (type, e) {
          var keyCode = e.keyCode || e.which;
          if (((e.metaKey && e.altKey) || (e.ctrlKey && e.shiftKey)) && keyCode == 73) {
            return true;
          }
        });
    });
    me.addListener('keyup', function (type, evt) {
      var keyCode = evt.keyCode || evt.which,
        rng,
        me = this;
      if (keyCode == keymap.Backspace) {
        if (me.fireEvent('delkeyup')) {
          return;
        }
        rng = me.selection.getRange();
        if (rng.collapsed) {
          var tmpNode,
            autoClearTagName = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
          if ((tmpNode = domUtils.findParentByTagName(rng.startContainer, autoClearTagName, true))) {
            if (domUtils.isEmptyBlock(tmpNode)) {
              var pre = tmpNode.previousSibling;
              if (pre && pre.nodeName != 'TABLE') {
                domUtils.remove(tmpNode);
                rng.setStartAtLast(pre).setCursor(false, true);
                return;
              } else {
                var next = tmpNode.nextSibling;
                if (next && next.nodeName != 'TABLE') {
                  domUtils.remove(tmpNode);
                  rng.setStartAtFirst(next).setCursor(false, true);
                  return;
                }
              }
            }
          }
          if (domUtils.isBody(rng.startContainer)) {
            var tmpNode = domUtils.createElement(me.document, 'p', {
              innerHTML: browser.ie ? domUtils.fillChar : '<br/>',
            });
            rng.insertNode(tmpNode).setStart(tmpNode, 0).setCursor(false, true);
          }
        }
        if (
          !collapsed &&
          (rng.startContainer.nodeType == 3 ||
            (rng.startContainer.nodeType == 1 && domUtils.isEmptyBlock(rng.startContainer)))
        ) {
          if (browser.ie) {
            var span = rng.document.createElement('span');
            rng.insertNode(span).setStartBefore(span).collapse(true);
            rng.select();
            domUtils.remove(span);
          } else {
            rng.select();
          }
        }
      }
    });
  };
  UE.plugins['fiximgclick'] = (function () {
    var elementUpdated = false;
    function Scale() {
      this.editor = null;
      this.resizer = null;
      this.cover = null;
      this.doc = document;
      this.prePos = { x: 0, y: 0 };
      this.startPos = { x: 0, y: 0 };
    }
    (function () {
      var rect = [
        [0, 0, -1, -1],
        [0, 0, 0, -1],
        [0, 0, 1, -1],
        [0, 0, -1, 0],
        [0, 0, 1, 0],
        [0, 0, -1, 1],
        [0, 0, 0, 1],
        [0, 0, 1, 1],
      ];
      Scale.prototype = {
        init: function (editor) {
          var me = this;
          me.editor = editor;
          me.startPos = this.prePos = { x: 0, y: 0 };
          me.dragId = -1;
          var hands = [],
            cover = (me.cover = document.createElement('div')),
            resizer = (me.resizer = document.createElement('div'));
          cover.id = me.editor.ui.id + '_imagescale_cover';
          cover.style.cssText =
            'position:absolute;display:none;z-index:' +
            me.editor.options.zIndex +
            ';filter:alpha(opacity=0); opacity:0;background:#CCC;';
          domUtils.on(cover, 'mousedown', function (e) {
            me.hide();
          });
          for (var i = 0; i < 8; i++) {
            hands.push('<span class="edui-editor-imagescale-hand' + i + '"></span>');
          }
          resizer.id = me.editor.ui.id + '_imagescale';
          resizer.className = 'edui-editor-imagescale';
          resizer.innerHTML = hands.join('');
          resizer.style.cssText += ';display:none;border:1px solid #3b77ff;z-index:' + me.editor.options.zIndex + ';';
          me.editor.ui.getDom().appendChild(cover);
          me.editor.ui.getDom().appendChild(resizer);
          me.initStyle();
          me.initEvents();
        },
        initStyle: function () {
          utils.cssRule(
            'imagescale',
            '.edui-editor-imagescale{display:none;position:absolute;border:1px solid #38B2CE;cursor:hand;-webkit-box-sizing: content-box;-moz-box-sizing: content-box;box-sizing: content-box;}' +
              '.edui-editor-imagescale span{position:absolute;width:6px;height:6px;overflow:hidden;font-size:0px;display:block;background-color:#3C9DD0;}' +
              '.edui-editor-imagescale .edui-editor-imagescale-hand0{cursor:nw-resize;top:0;margin-top:-4px;left:0;margin-left:-4px;}' +
              '.edui-editor-imagescale .edui-editor-imagescale-hand1{cursor:n-resize;top:0;margin-top:-4px;left:50%;margin-left:-4px;}' +
              '.edui-editor-imagescale .edui-editor-imagescale-hand2{cursor:ne-resize;top:0;margin-top:-4px;left:100%;margin-left:-3px;}' +
              '.edui-editor-imagescale .edui-editor-imagescale-hand3{cursor:w-resize;top:50%;margin-top:-4px;left:0;margin-left:-4px;}' +
              '.edui-editor-imagescale .edui-editor-imagescale-hand4{cursor:e-resize;top:50%;margin-top:-4px;left:100%;margin-left:-3px;}' +
              '.edui-editor-imagescale .edui-editor-imagescale-hand5{cursor:sw-resize;top:100%;margin-top:-3px;left:0;margin-left:-4px;}' +
              '.edui-editor-imagescale .edui-editor-imagescale-hand6{cursor:s-resize;top:100%;margin-top:-3px;left:50%;margin-left:-4px;}' +
              '.edui-editor-imagescale .edui-editor-imagescale-hand7{cursor:se-resize;top:100%;margin-top:-3px;left:100%;margin-left:-3px;}',
          );
        },
        initEvents: function () {
          var me = this;
          me.startPos.x = me.startPos.y = 0;
          me.isDraging = false;
        },
        _eventHandler: function (e) {
          var me = this;
          switch (e.type) {
            case 'mousedown':
              var hand = e.target || e.srcElement,
                hand;
              if (hand.className.indexOf('edui-editor-imagescale-hand') !== -1 && me.dragId === -1) {
                me.dragId = hand.className.slice(-1);
                me.startPos.x = me.prePos.x = e.clientX;
                me.startPos.y = me.prePos.y = e.clientY;
                domUtils.on(me.doc, 'mousemove', me.proxy(me._eventHandler, me));
              }
              break;
            case 'mousemove':
              if (me.dragId !== -1) {
                me.updateContainerStyle(me.dragId, { x: e.clientX - me.prePos.x, y: e.clientY - me.prePos.y });
                me.prePos.x = e.clientX;
                me.prePos.y = e.clientY;
                elementUpdated = true;
                me.updateTargetElement();
              }
              break;
            case 'mouseup':
              if (me.dragId !== -1) {
                me.updateContainerStyle(me.dragId, { x: e.clientX - me.prePos.x, y: e.clientY - me.prePos.y });
                me.updateTargetElement();
                if (me.target.parentNode) {
                  me.attachTo(me.target);
                }
                me.dragId = -1;
              }
              domUtils.un(me.doc, 'mousemove', me.proxy(me._eventHandler, me));
              if (elementUpdated) {
                elementUpdated = false;
                me.editor.fireEvent('contentchange');
              }
              break;
            default:
              break;
          }
        },
        updateTargetElement: function () {
          var me = this;
          domUtils.setStyles(me.target, { width: me.resizer.style.width, height: me.resizer.style.height });
          me.target.width = parseInt(me.resizer.style.width);
          me.target.height = parseInt(me.resizer.style.height);
          me.attachTo(me.target);
        },
        updateContainerStyle: function (dir, offset) {
          var me = this,
            dom = me.resizer,
            tmp;
          if (rect[dir][0] != 0) {
            tmp = parseInt(dom.style.left) + offset.x;
            dom.style.left = me._validScaledProp('left', tmp) + 'px';
          }
          if (rect[dir][1] != 0) {
            tmp = parseInt(dom.style.top) + offset.y;
            dom.style.top = me._validScaledProp('top', tmp) + 'px';
          }
          if (rect[dir][2] != 0) {
            tmp = dom.clientWidth + rect[dir][2] * offset.x;
            dom.style.width = me._validScaledProp('width', tmp) + 'px';
          }
          if (rect[dir][3] != 0) {
            tmp = dom.clientHeight + rect[dir][3] * offset.y;
            dom.style.height = me._validScaledProp('height', tmp) + 'px';
          }
        },
        _validScaledProp: function (prop, value) {
          var ele = this.resizer,
            wrap = document;
          value = isNaN(value) ? 0 : value;
          switch (prop) {
            case 'left':
              return value < 0
                ? 0
                : value + ele.clientWidth > wrap.clientWidth
                  ? wrap.clientWidth - ele.clientWidth
                  : value;
            case 'top':
              return value < 0
                ? 0
                : value + ele.clientHeight > wrap.clientHeight
                  ? wrap.clientHeight - ele.clientHeight
                  : value;
            case 'width':
              return value <= 0
                ? 1
                : value + ele.offsetLeft > wrap.clientWidth
                  ? wrap.clientWidth - ele.offsetLeft
                  : value;
            case 'height':
              return value <= 0
                ? 1
                : value + ele.offsetTop > wrap.clientHeight
                  ? wrap.clientHeight - ele.offsetTop
                  : value;
          }
        },
        hideCover: function () {
          this.cover.style.display = 'none';
        },
        showCover: function () {
          var me = this,
            editorPos = domUtils.getXY(me.editor.ui.getDom()),
            iframePos = domUtils.getXY(me.editor.iframe);
          domUtils.setStyles(me.cover, {
            width: me.editor.iframe.offsetWidth + 'px',
            height: me.editor.iframe.offsetHeight + 'px',
            top: iframePos.y - editorPos.y + 'px',
            left: iframePos.x - editorPos.x + 'px',
            position: 'absolute',
            display: '',
          });
        },
        show: function (targetObj) {
          var me = this;
          me.resizer.style.display = 'block';
          if (targetObj) {
            me.attachTo(targetObj);
          }
          domUtils.on(this.resizer, 'mousedown', me.proxy(me._eventHandler, me));
          domUtils.on(me.doc, 'mouseup', me.proxy(me._eventHandler, me));
          me.showCover();
          me.editor.fireEvent('afterscaleshow', me);
          me.editor.fireEvent('saveScene');
        },
        hide: function () {
          var me = this;
          me.hideCover();
          me.resizer.style.display = 'none';
          domUtils.un(me.resizer, 'mousedown', me.proxy(me._eventHandler, me));
          domUtils.un(me.doc, 'mouseup', me.proxy(me._eventHandler, me));
          me.editor.fireEvent('afterscalehide', me);
        },
        proxy: function (fn, context) {
          return function (e) {
            return fn.apply(context || this, arguments);
          };
        },
        attachTo: function (targetObj) {
          var me = this,
            target = (me.target = targetObj),
            resizer = this.resizer,
            imgPos = domUtils.getXY(target),
            iframePos = domUtils.getXY(me.editor.iframe),
            editorPos = domUtils.getXY(resizer.parentNode);
          domUtils.setStyles(resizer, {
            width: target.width + 'px',
            height: target.height + 'px',
            left:
              iframePos.x +
              imgPos.x -
              me.editor.getScrollLeft() -
              editorPos.x -
              parseInt(resizer.style.borderLeftWidth) +
              'px',
            top:
              iframePos.y +
              imgPos.y -
              me.editor.getScrollTop() -
              editorPos.y -
              parseInt(resizer.style.borderTopWidth) +
              'px',
          });
        },
      };
    })();
    return function () {
      var me = this,
        imageScale;
      me.setOpt('imageScaleEnabled', true);
      if (!browser.ie && me.options.imageScaleEnabled) {
        me.addListener('click', function (type, e) {
          var range = me.selection.getRange(),
            img = range.getClosedNode();
          if (img && img.tagName === 'IMG' && me.body.contentEditable !== 'false' && img === e.target) {
            if (
              img.getAttribute('anchorname') ||
              domUtils.hasClass(img, 'uep-loading') ||
              domUtils.hasClass(img, 'uep-loading-error')
            ) {
              return;
            }
            if (!imageScale) {
              imageScale = new Scale();
              imageScale.init(me);
              me.ui.getDom().appendChild(imageScale.resizer);
              var _keyDownHandler = function (e) {
                  imageScale.hide();
                  if (imageScale.target) {
                    me.selection.getRange().selectNode(imageScale.target).select();
                  }
                },
                _mouseDownHandler = function (e) {
                  var ele = e.target || e.srcElement;
                  if (ele && (ele.className === undefined || ele.className.indexOf('edui-editor-imagescale') === -1)) {
                    _keyDownHandler(e);
                  }
                },
                timer;
              me.addListener('afterscaleshow', function (e) {
                me.addListener('beforekeydown', _keyDownHandler);
                me.addListener('beforemousedown', _mouseDownHandler);
                domUtils.on(document, 'keydown', _keyDownHandler);
                domUtils.on(document, 'mousedown', _mouseDownHandler);
                me.selection.getNative().removeAllRanges();
              });
              me.addListener('afterscalehide', function (e) {
                me.removeListener('beforekeydown', _keyDownHandler);
                me.removeListener('beforemousedown', _mouseDownHandler);
                domUtils.un(document, 'keydown', _keyDownHandler);
                domUtils.un(document, 'mousedown', _mouseDownHandler);
                var target = imageScale.target;
                if (target.parentNode) {
                  me.selection.getRange().selectNode(target).select();
                }
              });
              domUtils.on(imageScale.resizer, 'mousedown', function (e) {
                me.selection.getNative().removeAllRanges();
                var ele = e.target || e.srcElement;
                if (ele && ele.className.indexOf('edui-editor-imagescale-hand') === -1) {
                  timer = setTimeout(function () {
                    imageScale.hide();
                    if (imageScale.target) me.selection.getRange().selectNode(ele).select();
                  }, 200);
                }
              });
              domUtils.on(imageScale.resizer, 'mouseup', function (e) {
                var ele = e.target || e.srcElement;
                if (ele && ele.className.indexOf('edui-editor-imagescale-hand') === -1) {
                  clearTimeout(timer);
                }
              });
            }
            imageScale.show(img);
          } else {
            if (imageScale && imageScale.resizer.style.display !== 'none') {
              imageScale.hide();
            }
          }
        });
      }
      if (browser.webkit) {
        me.addListener('click', function (type, e) {
          if (e.target.tagName === 'IMG' && me.body.contentEditable !== 'false') {
            var range = new dom.Range(me.document);
            range.selectNode(e.target).select();
          }
        });
      }
    };
  })();
  UE.plugin.register(
    'autolink',
    function () {
      var cont = 0;
      return !browser.ie
        ? {
            bindEvents: {
              reset: function () {
                cont = 0;
              },
              keydown: function (type, evt) {
                var me = this;
                var keyCode = evt.keyCode || evt.which;
                if (keyCode == 32 || keyCode == 13) {
                  var sel = me.selection.getNative(),
                    range = sel.getRangeAt(0).cloneRange(),
                    offset,
                    charCode;
                  var start = range.startContainer;
                  while (start.nodeType == 1 && range.startOffset > 0) {
                    start = range.startContainer.childNodes[range.startOffset - 1];
                    if (!start) {
                      break;
                    }
                    range.setStart(start, start.nodeType == 1 ? start.childNodes.length : start.nodeValue.length);
                    range.collapse(true);
                    start = range.startContainer;
                  }
                  do {
                    if (range.startOffset == 0) {
                      start = range.startContainer.previousSibling;
                      while (start && start.nodeType == 1) {
                        start = start.lastChild;
                      }
                      if (!start || domUtils.isFillChar(start)) {
                        break;
                      }
                      offset = start.nodeValue.length;
                    } else {
                      start = range.startContainer;
                      offset = range.startOffset;
                    }
                    range.setStart(start, offset - 1);
                    charCode = range.toString().charCodeAt(0);
                  } while (charCode != 160 && charCode != 32);
                  if (
                    range
                      .toString()
                      .replace(new RegExp(domUtils.fillChar, 'g'), '')
                      .match(/(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i)
                  ) {
                    while (range.toString().length) {
                      if (/^(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i.test(range.toString())) {
                        break;
                      }
                      try {
                        range.setStart(range.startContainer, range.startOffset + 1);
                      } catch (e) {
                        var start = range.startContainer;
                        while (!(next = start.nextSibling)) {
                          if (domUtils.isBody(start)) {
                            return;
                          }
                          start = start.parentNode;
                        }
                        range.setStart(next, 0);
                      }
                    }
                    if (domUtils.findParentByTagName(range.startContainer, 'a', true)) {
                      return;
                    }
                    var a = me.document.createElement('a'),
                      text = me.document.createTextNode(' '),
                      href;
                    me.undoManger && me.undoManger.save();
                    a.appendChild(range.extractContents());
                    a.href = a.innerHTML = a.innerHTML.replace(/<[^>]+>/g, '');
                    href = a.getAttribute('href').replace(new RegExp(domUtils.fillChar, 'g'), '');
                    href = /^(?:https?:\/\/)/gi.test(href) ? href : 'http://' + href;
                    a.setAttribute('_src', utils.html(href));
                    a.href = utils.html(href);
                    range.insertNode(a);
                    a.parentNode.insertBefore(text, a.nextSibling);
                    range.setStart(text, 0);
                    range.collapse(true);
                    sel.removeAllRanges();
                    sel.addRange(range);
                    me.undoManger && me.undoManger.save();
                  }
                }
              },
            },
          }
        : {};
    },
    function () {
      var keyCodes = { 37: 1, 38: 1, 39: 1, 40: 1, 13: 1, 32: 1 };
      function checkIsCludeLink(node) {
        if (node.nodeType == 3) {
          return null;
        }
        if (node.nodeName == 'A') {
          return node;
        }
        var lastChild = node.lastChild;
        while (lastChild) {
          if (lastChild.nodeName == 'A') {
            return lastChild;
          }
          if (lastChild.nodeType == 3) {
            if (domUtils.isWhitespace(lastChild)) {
              lastChild = lastChild.previousSibling;
              continue;
            }
            return null;
          }
          lastChild = lastChild.lastChild;
        }
      }
      browser.ie &&
        this.addListener('keyup', function (cmd, evt) {
          var me = this,
            keyCode = evt.keyCode;
          if (keyCodes[keyCode]) {
            var rng = me.selection.getRange();
            var start = rng.startContainer;
            if (keyCode == 13) {
              while (start && !domUtils.isBody(start) && !domUtils.isBlockElm(start)) {
                start = start.parentNode;
              }
              if (start && !domUtils.isBody(start) && start.nodeName == 'P') {
                var pre = start.previousSibling;
                if (pre && pre.nodeType == 1) {
                  var pre = checkIsCludeLink(pre);
                  if (pre && !pre.getAttribute('_href')) {
                    domUtils.remove(pre, true);
                  }
                }
              }
            } else if (keyCode == 32) {
              if (start.nodeType == 3 && /^\s$/.test(start.nodeValue)) {
                start = start.previousSibling;
                if (start && start.nodeName == 'A' && !start.getAttribute('_href')) {
                  domUtils.remove(start, true);
                }
              }
            } else {
              start = domUtils.findParentByTagName(start, 'a', true);
              if (start && !start.getAttribute('_href')) {
                var bk = rng.createBookmark();
                domUtils.remove(start, true);
                rng.moveToBookmark(bk).select(true);
              }
            }
          }
        });
    },
  );
  UE.plugins['autoheight'] = function () {
    var me = this;
    me.autoHeightEnabled = me.options.autoHeightEnabled !== false;
    if (!me.autoHeightEnabled) {
      return;
    }
    var bakOverflow,
      lastHeight = 0,
      options = me.options,
      currentHeight,
      timer;
    function adjustHeight() {
      var me = this;
      clearTimeout(timer);
      if (isFullscreen) return;
      if (!me.queryCommandState || (me.queryCommandState && me.queryCommandState('source') != 1)) {
        timer = setTimeout(function () {
          var node = me.body.lastChild;
          while (node && node.nodeType != 1) {
            node = node.previousSibling;
          }
          if (node && node.nodeType == 1) {
            node.style.clear = 'both';
            currentHeight = Math.max(
              domUtils.getXY(node).y + node.offsetHeight + 25,
              Math.max(options.minFrameHeight, options.initialFrameHeight),
            );
            if (currentHeight !== lastHeight) {
              me.iframe.parentNode.style.transition = 'width 0.3s, height 0.3s, easy-in-out';
              if (currentHeight !== parseInt(me.iframe.parentNode.style.height)) {
                me.iframe.parentNode.style.height = currentHeight + 'px';
              }
              me.body.style.height = currentHeight + 'px';
              lastHeight = currentHeight;
            }
            domUtils.removeStyle(node, 'clear');
          }
        }, 50);
      }
    }
    var isFullscreen;
    me.addListener('fullscreenchanged', function (cmd, f) {
      isFullscreen = f;
    });
    me.addListener('destroy', function () {
      domUtils.un(me.window, 'scroll', fixedScrollTop);
      me.removeListener('contentchange afterinserthtml keyup mouseup', adjustHeight);
    });
    me.enableAutoHeight = function () {
      var me = this;
      if (!me.autoHeightEnabled) {
        return;
      }
      var doc = me.document;
      me.autoHeightEnabled = true;
      bakOverflow = doc.body.style.overflowY;
      doc.body.style.overflowY = 'hidden';
      me.addListener('contentchange afterinserthtml keyup mouseup', adjustHeight);
      setTimeout(
        function () {
          adjustHeight.call(me);
        },
        browser.gecko ? 100 : 0,
      );
      me.fireEvent('autoheightchanged', me.autoHeightEnabled);
    };
    me.disableAutoHeight = function () {
      me.body.style.overflowY = bakOverflow || '';
      me.removeListener('contentchange', adjustHeight);
      me.removeListener('keyup', adjustHeight);
      me.removeListener('mouseup', adjustHeight);
      me.autoHeightEnabled = false;
      me.fireEvent('autoheightchanged', me.autoHeightEnabled);
    };
    me.on('setHeight', function () {
      me.disableAutoHeight();
    });
    me.addListener('ready', function () {
      me.enableAutoHeight();
      var timer;
      domUtils.on(browser.ie ? me.body : me.document, browser.webkit ? 'dragover' : 'drop', function () {
        clearTimeout(timer);
        timer = setTimeout(function () {
          adjustHeight.call(me);
        }, 100);
      });
      domUtils.on(me.window, 'scroll', fixedScrollTop);
    });
    var lastScrollY;
    function fixedScrollTop() {
      if (!me.window) return;
      if (lastScrollY === null) {
        lastScrollY = me.window.scrollY;
      } else if (me.window.scrollY == 0 && lastScrollY != 0) {
        me.window.scrollTo(0, 0);
        lastScrollY = null;
      }
    }
  };
  UE.plugins['autofloat'] = function () {
    var me = this,
      lang = me.getLang();
    me.setOpt({ topOffset: 0 });
    var optsAutoFloatEnabled = me.options.autoFloatEnabled !== false,
      topOffset = me.options.topOffset;
    if (!optsAutoFloatEnabled) {
      return;
    }
    var uiUtils = UE.ui.uiUtils,
      LteIE6 = browser.ie && browser.version <= 6,
      quirks = browser.quirks;
    function checkHasUI() {
      if (!UE.ui) {
        alert(lang.autofloatMsg);
        return 0;
      }
      return 1;
    }
    function fixIE6FixedPos() {
      var docStyle = document.body.style;
      docStyle.backgroundImage = 'url("about:blank")';
      docStyle.backgroundAttachment = 'fixed';
    }
    var bakCssText,
      placeHolder = document.createElement('div'),
      toolbarBox,
      orgTop,
      getPosition,
      flag = true;
    function setFloating() {
      var toobarBoxPos = domUtils.getXY(toolbarBox),
        origalFloat = domUtils.getComputedStyle(toolbarBox, 'position'),
        origalLeft = domUtils.getComputedStyle(toolbarBox, 'left');
      toolbarBox.style.width = toolbarBox.offsetWidth + 'px';
      toolbarBox.style.zIndex = me.options.zIndex * 1 + 1;
      toolbarBox.parentNode.insertBefore(placeHolder, toolbarBox);
      if (LteIE6 || (quirks && browser.ie)) {
        if (toolbarBox.style.position != 'absolute') {
          toolbarBox.style.position = 'absolute';
        }
        toolbarBox.style.top =
          (document.body.scrollTop || document.documentElement.scrollTop) - orgTop + topOffset + 'px';
      } else {
        if (browser.ie7Compat && flag) {
          flag = false;
          toolbarBox.style.left =
            domUtils.getXY(toolbarBox).x - document.documentElement.getBoundingClientRect().left + 2 + 'px';
        }
        if (toolbarBox.style.position != 'fixed') {
          toolbarBox.style.position = 'fixed';
          toolbarBox.style.top = topOffset + 'px';
          (origalFloat == 'absolute' || origalFloat == 'relative') &&
            parseFloat(origalLeft) &&
            (toolbarBox.style.left = toobarBoxPos.x + 'px');
        }
      }
    }
    function unsetFloating() {
      flag = true;
      if (placeHolder.parentNode) {
        placeHolder.parentNode.removeChild(placeHolder);
      }
      toolbarBox.style.cssText = bakCssText;
    }
    me.unsetFloating = unsetFloating;
    function updateFloating() {
      var rect3 = getPosition(me.container);
      var offset = me.options.toolbarTopOffset || 0;
      if (rect3.top < 0 && rect3.bottom - toolbarBox.offsetHeight > offset) {
        setFloating();
      } else {
        unsetFloating();
      }
    }
    var defer_updateFloating = utils.defer(
      function () {
        updateFloating();
      },
      browser.ie ? 200 : 100,
      true,
    );
    me.addListener('destroy', function () {
      domUtils.un(window, ['scroll', 'resize'], updateFloating);
      me.removeListener('keydown', defer_updateFloating);
    });
    me.addListener('ready', function () {
      if (checkHasUI(me)) {
        if (!me.ui) {
          return;
        }
        getPosition = uiUtils.getClientRect;
        toolbarBox = me.ui.getDom('toolbarbox');
        orgTop = getPosition(toolbarBox).top;
        bakCssText = toolbarBox.style.cssText;
        placeHolder.style.height = toolbarBox.offsetHeight + 'px';
        if (LteIE6) {
          fixIE6FixedPos();
        }
        domUtils.on(window, ['scroll', 'resize'], updateFloating);
        me.addListener('keydown', defer_updateFloating);
        me.addListener('beforefullscreenchange', function (t, enabled) {
          if (enabled) {
            unsetFloating();
          }
        });
        me.addListener('fullscreenchanged', function (t, enabled) {
          if (!enabled) {
            updateFloating();
          }
        });
        me.addListener('sourcemodechanged', function (t, enabled) {
          setTimeout(function () {
            updateFloating();
          }, 0);
        });
        me.addListener('clearDoc', function () {
          setTimeout(function () {
            updateFloating();
          }, 0);
        });
      }
    });
  };
  UE.plugins['video'] = function () {
    var me = this;
    function creatInsertStr(url, width, height, id, align, classname, type) {
      var str;
      switch (type) {
        case 'iframe':
          str =
            '<iframe class="' +
            classname +
            '" ' +
            ' src="' +
            utils.html(url) +
            '" width="' +
            width +
            '" height="' +
            height +
            '"' +
            ' frameborder=0 allowfullscreen>';
          break;
        case 'image':
          str =
            '<img ' +
            (id ? 'id="' + id + '"' : '') +
            ' width="' +
            width +
            '" height="' +
            height +
            '" _url="' +
            url +
            '" class="' +
            '"' +
            ' src="' +
            me.options.UEDITOR_HOME_URL +
            'themes/default/images/spacer.gif" style="background:url(' +
            me.options.UEDITOR_HOME_URL +
            'themes/default/images/videologo.gif) no-repeat center center; border:1px solid gray;' +
            (align ? 'float:' + align + ';' : '') +
            '" />';
          break;
        case 'embed':
          str =
            '<embed type="application/x-shockwave-flash" class="' +
            classname +
            '" pluginspage="http://www.macromedia.com/go/getflashplayer"' +
            ' src="' +
            utils.html(url) +
            '" width="' +
            width +
            '" height="' +
            height +
            '"' +
            (align ? ' style="float:' + align + '"' : '') +
            ' wmode="transparent" play="true" loop="false" menu="false" allowscriptaccess="never" allowfullscreen="true" >';
          break;
        case 'video':
          var ext = url.substr(url.lastIndexOf('.') + 1);
          if (ext == 'ogv') ext = 'ogg';
          str =
            '<video' +
            (id ? ' id="' + id + '"' : '') +
            ' class="' +
            classname +
            '" ' +
            (align ? ' style="float:' + align + '"' : '') +
            ' controls preload="none" width="' +
            width +
            '" height="' +
            height +
            '" src="' +
            url +
            '" data-setup="{}">' +
            '<source src="' +
            url +
            '" type="video/' +
            ext +
            '" /></video>';
          break;
      }
      return str;
    }
    function switchImgAndVideo(root, img2video) {
      utils.each(root.getNodesByTagName(img2video ? 'img' : 'embed video'), function (node) {
        var className = node.getAttr('class');
        if (className && className.indexOf('edui-faked-video') != -1) {
          var html = creatInsertStr(
            img2video ? node.getAttr('_url') : node.getAttr('src'),
            node.getAttr('width'),
            node.getAttr('height'),
            null,
            node.getStyle('float') || '',
            className,
            img2video ? 'embed' : 'image',
          );
          node.parentNode.replaceChild(UE.uNode.createElement(html), node);
        }
        if (className && className.indexOf('edui-upload-video') != -1) {
          var html = creatInsertStr(
            img2video ? node.getAttr('_url') : node.getAttr('src'),
            node.getAttr('width'),
            node.getAttr('height'),
            null,
            node.getStyle('float') || '',
            className,
            img2video ? 'video' : 'image',
          );
          node.parentNode.replaceChild(UE.uNode.createElement(html), node);
        }
      });
    }
    me.addOutputRule(function (root) {
      switchImgAndVideo(root, true);
    });
    me.addInputRule(function (root) {
      switchImgAndVideo(root);
    });
    me.commands['insertvideo'] = {
      execCommand: function (cmd, videoObjs, type) {
        videoObjs = utils.isArray(videoObjs) ? videoObjs : [videoObjs];
        if (me.fireEvent('beforeinsertvideo', videoObjs) === true) {
          return;
        }
        var html = [],
          id = 'tmpVideo',
          cl;
        for (var i = 0, vi, len = videoObjs.length; i < len; i++) {
          vi = videoObjs[i];
          var videoType = 'iframe';
          if (vi.url.match(/.mp4$/)) {
            videoType = 'video';
          }
          cl = videoType == 'iframe' ? 'edui-video-iframe' : 'edui-video-video';
          html.push(creatInsertStr(vi.url, vi.width || 420, vi.height || 280, id + i, null, cl, videoType));
        }
        me.execCommand('inserthtml', html.join(''), true);
        var rng = this.selection.getRange();
        me.fireEvent('afterinsertvideo', videoObjs);
      },
      queryCommandState: function () {
        var img = me.selection.getRange().getClosedNode(),
          flag =
            img &&
            (img.className == 'edui-video-iframe' ||
              img.className.indexOf('edui-video-iframe') != -1 ||
              img.className == 'edui-video-video' ||
              img.className.indexOf('edui-video-video') != -1);
        return flag ? 1 : 0;
      },
    };
  };
  UE.plugins['audio'] = function () {
    var me = this;
    function createAudioHtml(url, param) {
      param = param || {};
      var str = [
        '<audio',
        param.id ? ' id="' + param.id + '"' : '',
        param.cls ? ' class="' + param.cls + '"' : '',
        ' controls >',
        '<source src="' + url + '" type="audio/mpeg' + '" />',
        '</audio>',
      ];
      return str.join('');
    }
    function switchImgAndAudio(root, img2audio) {}
    me.addOutputRule(function (root) {
      switchImgAndAudio(root, true);
    });
    me.addInputRule(function (root) {
      switchImgAndAudio(root);
    });
    me.commands['insertaudio'] = {
      execCommand: function (cmd, audioObjs, type) {
        audioObjs = utils.isArray(audioObjs) ? audioObjs : [audioObjs];
        if (me.fireEvent('beforeinsertaudio', audioObjs) === true) {
          return;
        }
        var html = [];
        for (var i = 0, vi, len = audioObjs.length; i < len; i++) {
          vi = audioObjs[i];
          html.push(createAudioHtml(vi.url, { cls: 'edui-audio-audio' }));
        }
        me.execCommand('inserthtml', html.join(''), true);
        var rng = this.selection.getRange();
        me.fireEvent('afterinsertaudio', audioObjs);
      },
      queryCommandState: function () {
        var img = me.selection.getRange().getClosedNode(),
          flag = img && (img.className == 'edui-audio-audio' || img.className.indexOf('edui-audio-audio') != -1);
        return flag ? 1 : 0;
      },
    };
  };
  (function () {
    var UETable = (UE.UETable = function (table) {
      this.table = table;
      this.indexTable = [];
      this.selectedTds = [];
      this.cellsRange = {};
      this.update(table);
    });
    UETable.removeSelectedClass = function (cells) {
      utils.each(cells, function (cell) {
        domUtils.removeClasses(cell, 'selectTdClass');
      });
    };
    UETable.addSelectedClass = function (cells) {
      utils.each(cells, function (cell) {
        domUtils.addClass(cell, 'selectTdClass');
      });
    };
    UETable.isEmptyBlock = function (node) {
      var reg = new RegExp(domUtils.fillChar, 'g');
      if (node[browser.ie ? 'innerText' : 'textContent'].replace(/^\s*$/, '').replace(reg, '').length > 0) {
        return 0;
      }
      for (var i in dtd.$isNotEmpty)
        if (dtd.$isNotEmpty.hasOwnProperty(i)) {
          if (node.getElementsByTagName(i).length) {
            return 0;
          }
        }
      return 1;
    };
    UETable.getWidth = function (cell) {
      if (!cell) return 0;
      return parseInt(domUtils.getComputedStyle(cell, 'width'), 10);
    };
    UETable.getTableCellAlignState = function (cells) {
      !utils.isArray(cells) && (cells = [cells]);
      var result = {},
        status = ['align', 'valign'],
        tempStatus = null,
        isSame = true;
      utils.each(cells, function (cellNode) {
        utils.each(status, function (currentState) {
          tempStatus = cellNode.getAttribute(currentState);
          if (!result[currentState] && tempStatus) {
            result[currentState] = tempStatus;
          } else if (!result[currentState] || tempStatus !== result[currentState]) {
            isSame = false;
            return false;
          }
        });
        return isSame;
      });
      return isSame ? result : null;
    };
    UETable.getTableItemsByRange = function (editor) {
      var start = editor.selection.getStart();
      if (start && start.id && start.id.indexOf('_baidu_bookmark_start_') === 0 && start.nextSibling) {
        start = start.nextSibling;
      }
      var cell = start && domUtils.findParentByTagName(start, ['td', 'th'], true),
        tr = cell && cell.parentNode,
        table = tr && domUtils.findParentByTagName(tr, ['table']),
        caption = table && table.getElementsByTagName('caption')[0];
      return { cell: cell, tr: tr, table: table, caption: caption };
    };
    UETable.getUETableBySelected = function (editor) {
      var table = UETable.getTableItemsByRange(editor).table;
      if (table && table.ueTable && table.ueTable.selectedTds.length) {
        return table.ueTable;
      }
      return null;
    };
    UETable.getDefaultValue = function (editor, table) {
      var borderMap = { thin: '0px', medium: '1px', thick: '2px' },
        tableBorder,
        tdPadding,
        tdBorder,
        tmpValue;
      if (!table) {
        table = editor.document.createElement('table');
        table.insertRow(0).insertCell(0).innerHTML = 'xxx';
        editor.body.appendChild(table);
        var td = table.getElementsByTagName('td')[0];
        tmpValue = domUtils.getComputedStyle(table, 'border-left-width');
        tableBorder = parseInt(borderMap[tmpValue] || tmpValue, 10);
        tmpValue = domUtils.getComputedStyle(td, 'padding-left');
        tdPadding = parseInt(borderMap[tmpValue] || tmpValue, 10);
        tmpValue = domUtils.getComputedStyle(td, 'border-left-width');
        tdBorder = parseInt(borderMap[tmpValue] || tmpValue, 10);
        domUtils.remove(table);
        return { tableBorder: tableBorder, tdPadding: tdPadding, tdBorder: tdBorder };
      } else {
        td = table.getElementsByTagName('td')[0];
        tmpValue = domUtils.getComputedStyle(table, 'border-left-width');
        tableBorder = parseInt(borderMap[tmpValue] || tmpValue, 10);
        tmpValue = domUtils.getComputedStyle(td, 'padding-left');
        tdPadding = parseInt(borderMap[tmpValue] || tmpValue, 10);
        tmpValue = domUtils.getComputedStyle(td, 'border-left-width');
        tdBorder = parseInt(borderMap[tmpValue] || tmpValue, 10);
        return { tableBorder: tableBorder, tdPadding: tdPadding, tdBorder: tdBorder };
      }
    };
    UETable.getUETable = function (tdOrTable) {
      var tag = tdOrTable.tagName.toLowerCase();
      tdOrTable =
        tag == 'td' || tag == 'th' || tag == 'caption'
          ? domUtils.findParentByTagName(tdOrTable, 'table', true)
          : tdOrTable;
      if (!tdOrTable.ueTable) {
        tdOrTable.ueTable = new UETable(tdOrTable);
      }
      return tdOrTable.ueTable;
    };
    UETable.cloneCell = function (cell, ignoreMerge, keepPro) {
      if (!cell || utils.isString(cell)) {
        return this.table.ownerDocument.createElement(cell || 'td');
      }
      var flag = domUtils.hasClass(cell, 'selectTdClass');
      flag && domUtils.removeClasses(cell, 'selectTdClass');
      var tmpCell = cell.cloneNode(true);
      if (ignoreMerge) {
        tmpCell.rowSpan = tmpCell.colSpan = 1;
      }
      !keepPro && domUtils.removeAttributes(tmpCell, 'width height');
      !keepPro && domUtils.removeAttributes(tmpCell, 'style');
      tmpCell.style.borderLeftStyle = '';
      tmpCell.style.borderTopStyle = '';
      tmpCell.style.borderLeftColor = cell.style.borderRightColor;
      tmpCell.style.borderLeftWidth = cell.style.borderRightWidth;
      tmpCell.style.borderTopColor = cell.style.borderBottomColor;
      tmpCell.style.borderTopWidth = cell.style.borderBottomWidth;
      flag && domUtils.addClass(cell, 'selectTdClass');
      return tmpCell;
    };
    UETable.prototype = {
      getMaxRows: function () {
        var rows = this.table.rows,
          maxLen = 1;
        for (var i = 0, row; (row = rows[i]); i++) {
          var currentMax = 1;
          for (var j = 0, cj; (cj = row.cells[j++]); ) {
            currentMax = Math.max(cj.rowSpan || 1, currentMax);
          }
          maxLen = Math.max(currentMax + i, maxLen);
        }
        return maxLen;
      },
      getMaxCols: function () {
        var rows = this.table.rows,
          maxLen = 0,
          cellRows = {};
        for (var i = 0, row; (row = rows[i]); i++) {
          var cellsNum = 0;
          for (var j = 0, cj; (cj = row.cells[j++]); ) {
            cellsNum += cj.colSpan || 1;
            if (cj.rowSpan && cj.rowSpan > 1) {
              for (var k = 1; k < cj.rowSpan; k++) {
                if (!cellRows['row_' + (i + k)]) {
                  cellRows['row_' + (i + k)] = cj.colSpan || 1;
                } else {
                  cellRows['row_' + (i + k)]++;
                }
              }
            }
          }
          cellsNum += cellRows['row_' + i] || 0;
          maxLen = Math.max(cellsNum, maxLen);
        }
        return maxLen;
      },
      getCellColIndex: function (cell) {},
      getHSideCell: function (cell, right) {
        try {
          var cellInfo = this.getCellInfo(cell),
            previewRowIndex,
            previewColIndex;
          var len = this.selectedTds.length,
            range = this.cellsRange;
          if (
            (!right && (!len ? !cellInfo.colIndex : !range.beginColIndex)) ||
            (right && (!len ? cellInfo.colIndex == this.colsNum - 1 : range.endColIndex == this.colsNum - 1))
          )
            return null;
          previewRowIndex = !len ? cellInfo.rowIndex : range.beginRowIndex;
          previewColIndex = !right
            ? !len
              ? cellInfo.colIndex < 1
                ? 0
                : cellInfo.colIndex - 1
              : range.beginColIndex - 1
            : !len
              ? cellInfo.colIndex + 1
              : range.endColIndex + 1;
          return this.getCell(
            this.indexTable[previewRowIndex][previewColIndex].rowIndex,
            this.indexTable[previewRowIndex][previewColIndex].cellIndex,
          );
        } catch (e) {
          showError(e);
        }
      },
      getTabNextCell: function (cell, preRowIndex) {
        var cellInfo = this.getCellInfo(cell),
          rowIndex = preRowIndex || cellInfo.rowIndex,
          colIndex = cellInfo.colIndex + 1 + (cellInfo.colSpan - 1),
          nextCell;
        try {
          nextCell = this.getCell(
            this.indexTable[rowIndex][colIndex].rowIndex,
            this.indexTable[rowIndex][colIndex].cellIndex,
          );
        } catch (e) {
          try {
            rowIndex = rowIndex * 1 + 1;
            colIndex = 0;
            nextCell = this.getCell(
              this.indexTable[rowIndex][colIndex].rowIndex,
              this.indexTable[rowIndex][colIndex].cellIndex,
            );
          } catch (e) {}
        }
        return nextCell;
      },
      getVSideCell: function (cell, bottom, ignoreRange) {
        try {
          var cellInfo = this.getCellInfo(cell),
            nextRowIndex,
            nextColIndex;
          var len = this.selectedTds.length && !ignoreRange,
            range = this.cellsRange;
          if (
            (!bottom && cellInfo.rowIndex == 0) ||
            (bottom &&
              (!len ? cellInfo.rowIndex + cellInfo.rowSpan > this.rowsNum - 1 : range.endRowIndex == this.rowsNum - 1))
          )
            return null;
          nextRowIndex = !bottom
            ? !len
              ? cellInfo.rowIndex - 1
              : range.beginRowIndex - 1
            : !len
              ? cellInfo.rowIndex + cellInfo.rowSpan
              : range.endRowIndex + 1;
          nextColIndex = !len ? cellInfo.colIndex : range.beginColIndex;
          return this.getCell(
            this.indexTable[nextRowIndex][nextColIndex].rowIndex,
            this.indexTable[nextRowIndex][nextColIndex].cellIndex,
          );
        } catch (e) {
          showError(e);
        }
      },
      getSameEndPosCells: function (cell, xOrY) {
        try {
          var flag = xOrY.toLowerCase() === 'x',
            end = domUtils.getXY(cell)[flag ? 'x' : 'y'] + cell['offset' + (flag ? 'Width' : 'Height')],
            rows = this.table.rows,
            cells = null,
            returns = [];
          for (var i = 0; i < this.rowsNum; i++) {
            cells = rows[i].cells;
            for (var j = 0, tmpCell; (tmpCell = cells[j++]); ) {
              var tmpEnd = domUtils.getXY(tmpCell)[flag ? 'x' : 'y'] + tmpCell['offset' + (flag ? 'Width' : 'Height')];
              if (tmpEnd > end && flag) break;
              if (cell == tmpCell || end == tmpEnd) {
                if (tmpCell[flag ? 'colSpan' : 'rowSpan'] == 1) {
                  returns.push(tmpCell);
                }
                if (flag) break;
              }
            }
          }
          return returns;
        } catch (e) {
          showError(e);
        }
      },
      setCellContent: function (cell, content) {
        cell.innerHTML = content || (browser.ie ? domUtils.fillChar : '<br />');
      },
      cloneCell: UETable.cloneCell,
      getSameStartPosXCells: function (cell) {
        try {
          var start = domUtils.getXY(cell).x + cell.offsetWidth,
            rows = this.table.rows,
            cells,
            returns = [];
          for (var i = 0; i < this.rowsNum; i++) {
            cells = rows[i].cells;
            for (var j = 0, tmpCell; (tmpCell = cells[j++]); ) {
              var tmpStart = domUtils.getXY(tmpCell).x;
              if (tmpStart > start) break;
              if (tmpStart == start && tmpCell.colSpan == 1) {
                returns.push(tmpCell);
                break;
              }
            }
          }
          return returns;
        } catch (e) {
          showError(e);
        }
      },
      update: function (table) {
        this.table = table || this.table;
        this.selectedTds = [];
        this.cellsRange = {};
        this.indexTable = [];
        var rows = this.table.rows,
          rowsNum = this.getMaxRows(),
          dNum = rowsNum - rows.length,
          colsNum = this.getMaxCols();
        while (dNum--) {
          this.table.insertRow(rows.length);
        }
        this.rowsNum = rowsNum;
        this.colsNum = colsNum;
        for (var i = 0, len = rows.length; i < len; i++) {
          this.indexTable[i] = new Array(colsNum);
        }
        for (var rowIndex = 0, row; (row = rows[rowIndex]); rowIndex++) {
          for (var cellIndex = 0, cell, cells = row.cells; (cell = cells[cellIndex]); cellIndex++) {
            if (cell.rowSpan > rowsNum) {
              cell.rowSpan = rowsNum;
            }
            var colIndex = cellIndex,
              rowSpan = cell.rowSpan || 1,
              colSpan = cell.colSpan || 1;
            while (this.indexTable[rowIndex][colIndex]) colIndex++;
            for (var j = 0; j < rowSpan; j++) {
              for (var k = 0; k < colSpan; k++) {
                this.indexTable[rowIndex + j][colIndex + k] = {
                  rowIndex: rowIndex,
                  cellIndex: cellIndex,
                  colIndex: colIndex,
                  rowSpan: rowSpan,
                  colSpan: colSpan,
                };
              }
            }
          }
        }
        for (j = 0; j < rowsNum; j++) {
          for (k = 0; k < colsNum; k++) {
            if (this.indexTable[j][k] === undefined) {
              row = rows[j];
              cell = row.cells[row.cells.length - 1];
              cell = cell ? cell.cloneNode(true) : this.table.ownerDocument.createElement('td');
              this.setCellContent(cell);
              if (cell.colSpan !== 1) cell.colSpan = 1;
              if (cell.rowSpan !== 1) cell.rowSpan = 1;
              row.appendChild(cell);
              this.indexTable[j][k] = { rowIndex: j, cellIndex: cell.cellIndex, colIndex: k, rowSpan: 1, colSpan: 1 };
            }
          }
        }
        var tds = domUtils.getElementsByTagName(this.table, 'td'),
          selectTds = [];
        utils.each(tds, function (td) {
          if (domUtils.hasClass(td, 'selectTdClass')) {
            selectTds.push(td);
          }
        });
        if (selectTds.length) {
          var start = selectTds[0],
            end = selectTds[selectTds.length - 1],
            startInfo = this.getCellInfo(start),
            endInfo = this.getCellInfo(end);
          this.selectedTds = selectTds;
          this.cellsRange = {
            beginRowIndex: startInfo.rowIndex,
            beginColIndex: startInfo.colIndex,
            endRowIndex: endInfo.rowIndex + endInfo.rowSpan - 1,
            endColIndex: endInfo.colIndex + endInfo.colSpan - 1,
          };
        }
        if (!domUtils.hasClass(this.table.rows[0], 'firstRow')) {
          domUtils.addClass(this.table.rows[0], 'firstRow');
          for (var i = 1; i < this.table.rows.length; i++) {
            domUtils.removeClasses(this.table.rows[i], 'firstRow');
          }
        }
      },
      getCellInfo: function (cell) {
        if (!cell) return;
        var cellIndex = cell.cellIndex,
          rowIndex = cell.parentNode.rowIndex,
          rowInfo = this.indexTable[rowIndex],
          numCols = this.colsNum;
        for (var colIndex = cellIndex; colIndex < numCols; colIndex++) {
          var cellInfo = rowInfo[colIndex];
          if (cellInfo.rowIndex === rowIndex && cellInfo.cellIndex === cellIndex) {
            return cellInfo;
          }
        }
      },
      getCell: function (rowIndex, cellIndex) {
        return (rowIndex < this.rowsNum && this.table.rows[rowIndex].cells[cellIndex]) || null;
      },
      deleteCell: function (cell, rowIndex) {
        rowIndex = typeof rowIndex == 'number' ? rowIndex : cell.parentNode.rowIndex;
        var row = this.table.rows[rowIndex];
        row.deleteCell(cell.cellIndex);
      },
      getCellsRange: function (cellA, cellB) {
        function checkRange(beginRowIndex, beginColIndex, endRowIndex, endColIndex) {
          var tmpBeginRowIndex = beginRowIndex,
            tmpBeginColIndex = beginColIndex,
            tmpEndRowIndex = endRowIndex,
            tmpEndColIndex = endColIndex,
            cellInfo,
            colIndex,
            rowIndex;
          if (beginRowIndex > 0) {
            for (colIndex = beginColIndex; colIndex < endColIndex; colIndex++) {
              cellInfo = me.indexTable[beginRowIndex][colIndex];
              rowIndex = cellInfo.rowIndex;
              if (rowIndex < beginRowIndex) {
                tmpBeginRowIndex = Math.min(rowIndex, tmpBeginRowIndex);
              }
            }
          }
          if (endColIndex < me.colsNum) {
            for (rowIndex = beginRowIndex; rowIndex < endRowIndex; rowIndex++) {
              cellInfo = me.indexTable[rowIndex][endColIndex];
              colIndex = cellInfo.colIndex + cellInfo.colSpan - 1;
              if (colIndex > endColIndex) {
                tmpEndColIndex = Math.max(colIndex, tmpEndColIndex);
              }
            }
          }
          if (endRowIndex < me.rowsNum) {
            for (colIndex = beginColIndex; colIndex < endColIndex; colIndex++) {
              cellInfo = me.indexTable[endRowIndex][colIndex];
              rowIndex = cellInfo.rowIndex + cellInfo.rowSpan - 1;
              if (rowIndex > endRowIndex) {
                tmpEndRowIndex = Math.max(rowIndex, tmpEndRowIndex);
              }
            }
          }
          if (beginColIndex > 0) {
            for (rowIndex = beginRowIndex; rowIndex < endRowIndex; rowIndex++) {
              cellInfo = me.indexTable[rowIndex][beginColIndex];
              colIndex = cellInfo.colIndex;
              if (colIndex < beginColIndex) {
                tmpBeginColIndex = Math.min(cellInfo.colIndex, tmpBeginColIndex);
              }
            }
          }
          if (
            tmpBeginRowIndex != beginRowIndex ||
            tmpBeginColIndex != beginColIndex ||
            tmpEndRowIndex != endRowIndex ||
            tmpEndColIndex != endColIndex
          ) {
            return checkRange(tmpBeginRowIndex, tmpBeginColIndex, tmpEndRowIndex, tmpEndColIndex);
          } else {
            return {
              beginRowIndex: beginRowIndex,
              beginColIndex: beginColIndex,
              endRowIndex: endRowIndex,
              endColIndex: endColIndex,
            };
          }
        }
        try {
          var me = this,
            cellAInfo = me.getCellInfo(cellA);
          if (cellA === cellB) {
            return {
              beginRowIndex: cellAInfo.rowIndex,
              beginColIndex: cellAInfo.colIndex,
              endRowIndex: cellAInfo.rowIndex + cellAInfo.rowSpan - 1,
              endColIndex: cellAInfo.colIndex + cellAInfo.colSpan - 1,
            };
          }
          var cellBInfo = me.getCellInfo(cellB);
          var beginRowIndex = Math.min(cellAInfo.rowIndex, cellBInfo.rowIndex),
            beginColIndex = Math.min(cellAInfo.colIndex, cellBInfo.colIndex),
            endRowIndex = Math.max(
              cellAInfo.rowIndex + cellAInfo.rowSpan - 1,
              cellBInfo.rowIndex + cellBInfo.rowSpan - 1,
            ),
            endColIndex = Math.max(
              cellAInfo.colIndex + cellAInfo.colSpan - 1,
              cellBInfo.colIndex + cellBInfo.colSpan - 1,
            );
          return checkRange(beginRowIndex, beginColIndex, endRowIndex, endColIndex);
        } catch (e) {}
      },
      getCells: function (range) {
        this.clearSelected();
        var beginRowIndex = range.beginRowIndex,
          beginColIndex = range.beginColIndex,
          endRowIndex = range.endRowIndex,
          endColIndex = range.endColIndex,
          cellInfo,
          rowIndex,
          colIndex,
          tdHash = {},
          returnTds = [];
        for (var i = beginRowIndex; i <= endRowIndex; i++) {
          for (var j = beginColIndex; j <= endColIndex; j++) {
            cellInfo = this.indexTable[i][j];
            rowIndex = cellInfo.rowIndex;
            colIndex = cellInfo.colIndex;
            var key = rowIndex + '|' + colIndex;
            if (tdHash[key]) continue;
            tdHash[key] = 1;
            if (
              rowIndex < i ||
              colIndex < j ||
              rowIndex + cellInfo.rowSpan - 1 > endRowIndex ||
              colIndex + cellInfo.colSpan - 1 > endColIndex
            ) {
              return null;
            }
            returnTds.push(this.getCell(rowIndex, cellInfo.cellIndex));
          }
        }
        return returnTds;
      },
      clearSelected: function () {
        UETable.removeSelectedClass(this.selectedTds);
        this.selectedTds = [];
        this.cellsRange = {};
      },
      setSelected: function (range) {
        var cells = this.getCells(range);
        UETable.addSelectedClass(cells);
        this.selectedTds = cells;
        this.cellsRange = range;
      },
      isFullRow: function () {
        var range = this.cellsRange;
        return range.endColIndex - range.beginColIndex + 1 == this.colsNum;
      },
      isFullCol: function () {
        var range = this.cellsRange,
          table = this.table,
          ths = table.getElementsByTagName('th'),
          rows = range.endRowIndex - range.beginRowIndex + 1;
        return !ths.length ? rows == this.rowsNum : rows == this.rowsNum || rows == this.rowsNum - 1;
      },
      getNextCell: function (cell, bottom, ignoreRange) {
        try {
          var cellInfo = this.getCellInfo(cell),
            nextRowIndex,
            nextColIndex;
          var len = this.selectedTds.length && !ignoreRange,
            range = this.cellsRange;
          if (
            (!bottom && cellInfo.rowIndex == 0) ||
            (bottom &&
              (!len ? cellInfo.rowIndex + cellInfo.rowSpan > this.rowsNum - 1 : range.endRowIndex == this.rowsNum - 1))
          )
            return null;
          nextRowIndex = !bottom
            ? !len
              ? cellInfo.rowIndex - 1
              : range.beginRowIndex - 1
            : !len
              ? cellInfo.rowIndex + cellInfo.rowSpan
              : range.endRowIndex + 1;
          nextColIndex = !len ? cellInfo.colIndex : range.beginColIndex;
          return this.getCell(
            this.indexTable[nextRowIndex][nextColIndex].rowIndex,
            this.indexTable[nextRowIndex][nextColIndex].cellIndex,
          );
        } catch (e) {
          showError(e);
        }
      },
      getPreviewCell: function (cell, top) {
        try {
          var cellInfo = this.getCellInfo(cell),
            previewRowIndex,
            previewColIndex;
          var len = this.selectedTds.length,
            range = this.cellsRange;
          if (
            (!top && (!len ? !cellInfo.colIndex : !range.beginColIndex)) ||
            (top && (!len ? cellInfo.rowIndex > this.colsNum - 1 : range.endColIndex == this.colsNum - 1))
          )
            return null;
          previewRowIndex = !top
            ? !len
              ? cellInfo.rowIndex
              : range.beginRowIndex
            : !len
              ? cellInfo.rowIndex < 1
                ? 0
                : cellInfo.rowIndex - 1
              : range.beginRowIndex;
          previewColIndex = !top
            ? !len
              ? cellInfo.colIndex < 1
                ? 0
                : cellInfo.colIndex - 1
              : range.beginColIndex - 1
            : !len
              ? cellInfo.colIndex
              : range.endColIndex + 1;
          return this.getCell(
            this.indexTable[previewRowIndex][previewColIndex].rowIndex,
            this.indexTable[previewRowIndex][previewColIndex].cellIndex,
          );
        } catch (e) {
          showError(e);
        }
      },
      moveContent: function (cellTo, cellFrom) {
        if (UETable.isEmptyBlock(cellFrom)) return;
        if (UETable.isEmptyBlock(cellTo)) {
          cellTo.innerHTML = cellFrom.innerHTML;
          return;
        }
        var child = cellTo.lastChild;
        if (child.nodeType == 3 || !dtd.$block[child.tagName]) {
          cellTo.appendChild(cellTo.ownerDocument.createElement('br'));
        }
        while ((child = cellFrom.firstChild)) {
          cellTo.appendChild(child);
        }
      },
      mergeRight: function (cell) {
        var cellInfo = this.getCellInfo(cell),
          rightColIndex = cellInfo.colIndex + cellInfo.colSpan,
          rightCellInfo = this.indexTable[cellInfo.rowIndex][rightColIndex],
          rightCell = this.getCell(rightCellInfo.rowIndex, rightCellInfo.cellIndex);
        cell.colSpan = cellInfo.colSpan + rightCellInfo.colSpan;
        cell.removeAttribute('width');
        this.moveContent(cell, rightCell);
        this.deleteCell(rightCell, rightCellInfo.rowIndex);
        this.update();
      },
      mergeDown: function (cell) {
        var cellInfo = this.getCellInfo(cell),
          downRowIndex = cellInfo.rowIndex + cellInfo.rowSpan,
          downCellInfo = this.indexTable[downRowIndex][cellInfo.colIndex],
          downCell = this.getCell(downCellInfo.rowIndex, downCellInfo.cellIndex);
        cell.rowSpan = cellInfo.rowSpan + downCellInfo.rowSpan;
        cell.removeAttribute('height');
        this.moveContent(cell, downCell);
        this.deleteCell(downCell, downCellInfo.rowIndex);
        this.update();
      },
      mergeRange: function () {
        var range = this.cellsRange,
          leftTopCell = this.getCell(
            range.beginRowIndex,
            this.indexTable[range.beginRowIndex][range.beginColIndex].cellIndex,
          );
        var cells = this.getCells(range);
        for (var i = 0, ci; (ci = cells[i++]); ) {
          if (ci !== leftTopCell) {
            this.moveContent(leftTopCell, ci);
            this.deleteCell(ci);
          }
        }
        leftTopCell.rowSpan = range.endRowIndex - range.beginRowIndex + 1;
        leftTopCell.rowSpan > 1 && leftTopCell.removeAttribute('height');
        leftTopCell.colSpan = range.endColIndex - range.beginColIndex + 1;
        leftTopCell.colSpan > 1 && leftTopCell.removeAttribute('width');
        if (leftTopCell.rowSpan == this.rowsNum && leftTopCell.colSpan != 1) {
          leftTopCell.colSpan = 1;
        }
        if (leftTopCell.colSpan == this.colsNum && leftTopCell.rowSpan != 1) {
          var rowIndex = leftTopCell.parentNode.rowIndex;
          if (this.table.deleteRow) {
            for (var i = rowIndex + 1, curIndex = rowIndex + 1, len = leftTopCell.rowSpan; i < len; i++) {
              this.table.deleteRow(curIndex);
            }
          } else {
            for (var i = 0, len = leftTopCell.rowSpan - 1; i < len; i++) {
              var row = this.table.rows[rowIndex + 1];
              row.parentNode.removeChild(row);
            }
          }
          leftTopCell.rowSpan = 1;
        }
        this.update();
      },
      insertRow: function (rowIndex, sourceCell) {
        var numCols = this.colsNum,
          table = this.table,
          row = table.insertRow(rowIndex),
          cell,
          thead = null,
          isInsertTitle = typeof sourceCell == 'string' && sourceCell.toUpperCase() == 'TH';
        function replaceTdToTh(colIndex, cell, tableRow) {
          if (colIndex == 0) {
            var tr = tableRow.nextSibling || tableRow.previousSibling,
              th = tr.cells[colIndex];
            if (th.tagName == 'TH') {
              th = cell.ownerDocument.createElement('th');
              th.appendChild(cell.firstChild);
              tableRow.insertBefore(th, cell);
              domUtils.remove(cell);
            }
          } else {
            if (cell.tagName == 'TH') {
              var td = cell.ownerDocument.createElement('td');
              td.appendChild(cell.firstChild);
              tableRow.insertBefore(td, cell);
              domUtils.remove(cell);
            }
          }
        }
        if (rowIndex == 0 || rowIndex == this.rowsNum) {
          for (var colIndex = 0; colIndex < numCols; colIndex++) {
            cell = this.cloneCell(sourceCell, true);
            this.setCellContent(cell);
            cell.getAttribute('vAlign') && cell.setAttribute('vAlign', cell.getAttribute('vAlign'));
            row.appendChild(cell);
            if (!isInsertTitle) replaceTdToTh(colIndex, cell, row);
          }
          if (isInsertTitle) {
            thead = table.createTHead();
            thead.insertBefore(row, thead.firstChild);
          }
        } else {
          var infoRow = this.indexTable[rowIndex],
            cellIndex = 0;
          for (colIndex = 0; colIndex < numCols; colIndex++) {
            var cellInfo = infoRow[colIndex];
            if (cellInfo.rowIndex < rowIndex) {
              cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex);
              cell.rowSpan = cellInfo.rowSpan + 1;
            } else {
              cell = this.cloneCell(sourceCell, true);
              this.setCellContent(cell);
              row.appendChild(cell);
            }
            if (!isInsertTitle) replaceTdToTh(colIndex, cell, row);
          }
        }
        this.update();
        return row;
      },
      deleteRow: function (rowIndex) {
        var row = this.table.rows[rowIndex],
          infoRow = this.indexTable[rowIndex],
          colsNum = this.colsNum,
          count = 0;
        for (var colIndex = 0; colIndex < colsNum; ) {
          var cellInfo = infoRow[colIndex],
            cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex);
          if (cell.rowSpan > 1) {
            if (cellInfo.rowIndex == rowIndex) {
              var clone = cell.cloneNode(true);
              clone.rowSpan = cell.rowSpan - 1;
              clone.innerHTML = '';
              cell.rowSpan = 1;
              var nextRowIndex = rowIndex + 1,
                nextRow = this.table.rows[nextRowIndex],
                insertCellIndex,
                preMerged = this.getPreviewMergedCellsNum(nextRowIndex, colIndex) - count;
              if (preMerged < colIndex) {
                insertCellIndex = colIndex - preMerged - 1;
                domUtils.insertAfter(nextRow.cells[insertCellIndex], clone);
              } else {
                if (nextRow.cells.length) nextRow.insertBefore(clone, nextRow.cells[0]);
              }
              count += 1;
            }
          }
          colIndex += cell.colSpan || 1;
        }
        var deleteTds = [],
          cacheMap = {};
        for (colIndex = 0; colIndex < colsNum; colIndex++) {
          var tmpRowIndex = infoRow[colIndex].rowIndex,
            tmpCellIndex = infoRow[colIndex].cellIndex,
            key = tmpRowIndex + '_' + tmpCellIndex;
          if (cacheMap[key]) continue;
          cacheMap[key] = 1;
          cell = this.getCell(tmpRowIndex, tmpCellIndex);
          deleteTds.push(cell);
        }
        var mergeTds = [];
        utils.each(deleteTds, function (td) {
          if (td.rowSpan == 1) {
            td.parentNode.removeChild(td);
          } else {
            mergeTds.push(td);
          }
        });
        utils.each(mergeTds, function (td) {
          td.rowSpan--;
        });
        row.parentNode.removeChild(row);
        this.update();
      },
      insertCol: function (colIndex, sourceCell, defaultValue) {
        var rowsNum = this.rowsNum,
          rowIndex = 0,
          tableRow,
          cell,
          backWidth = parseInt(
            (this.table.offsetWidth - (this.colsNum + 1) * 20 - (this.colsNum + 1)) / (this.colsNum + 1),
            10,
          ),
          isInsertTitleCol = typeof sourceCell == 'string' && sourceCell.toUpperCase() == 'TH';
        function replaceTdToTh(rowIndex, cell, tableRow) {
          if (rowIndex == 0) {
            var th = cell.nextSibling || cell.previousSibling;
            if (th.tagName == 'TH') {
              th = cell.ownerDocument.createElement('th');
              th.appendChild(cell.firstChild);
              tableRow.insertBefore(th, cell);
              domUtils.remove(cell);
            }
          } else {
            if (cell.tagName == 'TH') {
              var td = cell.ownerDocument.createElement('td');
              td.appendChild(cell.firstChild);
              tableRow.insertBefore(td, cell);
              domUtils.remove(cell);
            }
          }
        }
        var preCell;
        if (colIndex == 0 || colIndex == this.colsNum) {
          for (; rowIndex < rowsNum; rowIndex++) {
            tableRow = this.table.rows[rowIndex];
            preCell = tableRow.cells[colIndex == 0 ? colIndex : tableRow.cells.length];
            cell = this.cloneCell(sourceCell, true);
            this.setCellContent(cell);
            cell.setAttribute('vAlign', cell.getAttribute('vAlign'));
            preCell && cell.setAttribute('width', preCell.getAttribute('width'));
            if (!colIndex) {
              tableRow.insertBefore(cell, tableRow.cells[0]);
            } else {
              domUtils.insertAfter(tableRow.cells[tableRow.cells.length - 1], cell);
            }
            if (!isInsertTitleCol) replaceTdToTh(rowIndex, cell, tableRow);
          }
        } else {
          for (; rowIndex < rowsNum; rowIndex++) {
            var cellInfo = this.indexTable[rowIndex][colIndex];
            if (cellInfo.colIndex < colIndex) {
              cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex);
              cell.colSpan = cellInfo.colSpan + 1;
            } else {
              tableRow = this.table.rows[rowIndex];
              preCell = tableRow.cells[cellInfo.cellIndex];
              cell = this.cloneCell(sourceCell, true);
              this.setCellContent(cell);
              cell.setAttribute('vAlign', cell.getAttribute('vAlign'));
              preCell && cell.setAttribute('width', preCell.getAttribute('width'));
              preCell ? tableRow.insertBefore(cell, preCell) : tableRow.appendChild(cell);
            }
            if (!isInsertTitleCol) replaceTdToTh(rowIndex, cell, tableRow);
          }
        }
        this.update();
        this.updateWidth(backWidth, defaultValue || { tdPadding: 10, tdBorder: 1 });
      },
      updateWidth: function (width, defaultValue) {
        var table = this.table,
          tmpWidth = UETable.getWidth(table) - defaultValue.tdPadding * 2 - defaultValue.tdBorder + width;
        if (tmpWidth < table.ownerDocument.body.offsetWidth) {
          table.setAttribute('width', tmpWidth);
          return;
        }
        var tds = domUtils.getElementsByTagName(this.table, 'td th');
        utils.each(tds, function (td) {
          td.setAttribute('width', width);
        });
      },
      deleteCol: function (colIndex) {
        var indexTable = this.indexTable,
          tableRows = this.table.rows,
          backTableWidth = this.table.getAttribute('width'),
          backTdWidth = 0,
          rowsNum = this.rowsNum,
          cacheMap = {};
        for (var rowIndex = 0; rowIndex < rowsNum; ) {
          var infoRow = indexTable[rowIndex],
            cellInfo = infoRow[colIndex],
            key = cellInfo.rowIndex + '_' + cellInfo.colIndex;
          if (cacheMap[key]) continue;
          cacheMap[key] = 1;
          var cell = this.getCell(cellInfo.rowIndex, cellInfo.cellIndex);
          if (!backTdWidth) backTdWidth = cell && parseInt(cell.offsetWidth / cell.colSpan, 10).toFixed(0);
          if (cell.colSpan > 1) {
            cell.colSpan--;
          } else {
            tableRows[rowIndex].deleteCell(cellInfo.cellIndex);
          }
          rowIndex += cellInfo.rowSpan || 1;
        }
        this.table.setAttribute('width', backTableWidth - backTdWidth);
        this.update();
      },
      splitToCells: function (cell) {
        var me = this,
          cells = this.splitToRows(cell);
        utils.each(cells, function (cell) {
          me.splitToCols(cell);
        });
      },
      splitToRows: function (cell) {
        var cellInfo = this.getCellInfo(cell),
          rowIndex = cellInfo.rowIndex,
          colIndex = cellInfo.colIndex,
          results = [];
        cell.rowSpan = 1;
        results.push(cell);
        for (var i = rowIndex, endRow = rowIndex + cellInfo.rowSpan; i < endRow; i++) {
          if (i == rowIndex) continue;
          var tableRow = this.table.rows[i],
            tmpCell = tableRow.insertCell(colIndex - this.getPreviewMergedCellsNum(i, colIndex));
          tmpCell.colSpan = cellInfo.colSpan;
          this.setCellContent(tmpCell);
          tmpCell.setAttribute('vAlign', cell.getAttribute('vAlign'));
          tmpCell.setAttribute('align', cell.getAttribute('align'));
          if (cell.style.cssText) {
            tmpCell.style.cssText = cell.style.cssText;
          }
          results.push(tmpCell);
        }
        this.update();
        return results;
      },
      getPreviewMergedCellsNum: function (rowIndex, colIndex) {
        var indexRow = this.indexTable[rowIndex],
          num = 0;
        for (var i = 0; i < colIndex; ) {
          var colSpan = indexRow[i].colSpan,
            tmpRowIndex = indexRow[i].rowIndex;
          num += colSpan - (tmpRowIndex == rowIndex ? 1 : 0);
          i += colSpan;
        }
        return num;
      },
      splitToCols: function (cell) {
        var backWidth = (cell.offsetWidth / cell.colSpan - 22).toFixed(0),
          cellInfo = this.getCellInfo(cell),
          rowIndex = cellInfo.rowIndex,
          colIndex = cellInfo.colIndex,
          results = [];
        cell.colSpan = 1;
        cell.setAttribute('width', backWidth);
        results.push(cell);
        for (var j = colIndex, endCol = colIndex + cellInfo.colSpan; j < endCol; j++) {
          if (j == colIndex) continue;
          var tableRow = this.table.rows[rowIndex],
            tmpCell = tableRow.insertCell(this.indexTable[rowIndex][j].cellIndex + 1);
          tmpCell.rowSpan = cellInfo.rowSpan;
          this.setCellContent(tmpCell);
          tmpCell.setAttribute('vAlign', cell.getAttribute('vAlign'));
          tmpCell.setAttribute('align', cell.getAttribute('align'));
          tmpCell.setAttribute('width', backWidth);
          if (cell.style.cssText) {
            tmpCell.style.cssText = cell.style.cssText;
          }
          if (cell.tagName == 'TH') {
            var th = cell.ownerDocument.createElement('th');
            th.appendChild(tmpCell.firstChild);
            th.setAttribute('vAlign', cell.getAttribute('vAlign'));
            th.rowSpan = tmpCell.rowSpan;
            tableRow.insertBefore(th, tmpCell);
            domUtils.remove(tmpCell);
          }
          results.push(tmpCell);
        }
        this.update();
        return results;
      },
      isLastCell: function (cell, rowsNum, colsNum) {
        rowsNum = rowsNum || this.rowsNum;
        colsNum = colsNum || this.colsNum;
        var cellInfo = this.getCellInfo(cell);
        return cellInfo.rowIndex + cellInfo.rowSpan == rowsNum && cellInfo.colIndex + cellInfo.colSpan == colsNum;
      },
      getLastCell: function (cells) {
        cells = cells || this.table.getElementsByTagName('td');
        var firstInfo = this.getCellInfo(cells[0]);
        var me = this,
          last = cells[0],
          tr = last.parentNode,
          cellsNum = 0,
          cols = 0,
          rows;
        utils.each(cells, function (cell) {
          if (cell.parentNode == tr) cols += cell.colSpan || 1;
          cellsNum += cell.rowSpan * cell.colSpan || 1;
        });
        rows = cellsNum / cols;
        utils.each(cells, function (cell) {
          if (me.isLastCell(cell, rows, cols)) {
            last = cell;
            return false;
          }
        });
        return last;
      },
      selectRow: function (rowIndex) {
        var indexRow = this.indexTable[rowIndex],
          start = this.getCell(indexRow[0].rowIndex, indexRow[0].cellIndex),
          end = this.getCell(indexRow[this.colsNum - 1].rowIndex, indexRow[this.colsNum - 1].cellIndex),
          range = this.getCellsRange(start, end);
        this.setSelected(range);
      },
      selectTable: function () {
        var tds = this.table.getElementsByTagName('td'),
          range = this.getCellsRange(tds[0], tds[tds.length - 1]);
        this.setSelected(range);
      },
      setBackground: function (cells, value) {
        if (typeof value === 'string') {
          utils.each(cells, function (cell) {
            cell.style.backgroundColor = value;
          });
        } else if (typeof value === 'object') {
          value = utils.extend({ repeat: true, colorList: ['#ddd', '#fff'] }, value);
          var rowIndex = this.getCellInfo(cells[0]).rowIndex,
            count = 0,
            colors = value.colorList,
            getColor = function (list, index, repeat) {
              return list[index] ? list[index] : repeat ? list[index % list.length] : '';
            };
          for (var i = 0, cell; (cell = cells[i++]); ) {
            var cellInfo = this.getCellInfo(cell);
            cell.style.backgroundColor = getColor(
              colors,
              rowIndex + count == cellInfo.rowIndex ? count : ++count,
              value.repeat,
            );
          }
        }
      },
      removeBackground: function (cells) {
        utils.each(cells, function (cell) {
          cell.style.backgroundColor = '';
        });
      },
    };
    function showError(e) {}
  })();
  (function () {
    var UT = UE.UETable,
      getTableItemsByRange = function (editor) {
        return UT.getTableItemsByRange(editor);
      },
      getUETableBySelected = function (editor) {
        return UT.getUETableBySelected(editor);
      },
      getDefaultValue = function (editor, table) {
        return UT.getDefaultValue(editor, table);
      },
      getUETable = function (tdOrTable) {
        return UT.getUETable(tdOrTable);
      };
    UE.commands['inserttable'] = {
      queryCommandState: function () {
        return getTableItemsByRange(this).table ? -1 : 0;
      },
      execCommand: function (cmd, opt) {
        function createTable(opt, tdWidth) {
          var html = [],
            rowsNum = opt.numRows,
            colsNum = opt.numCols;
          for (var r = 0; r < rowsNum; r++) {
            html.push('<tr' + (r == 0 ? ' class="firstRow"' : '') + '>');
            for (var c = 0; c < colsNum; c++) {
              html.push(
                '<td width="' +
                  tdWidth +
                  '"  vAlign="' +
                  opt.tdvalign +
                  '" >' +
                  (browser.ie && browser.version < 11 ? domUtils.fillChar : '<br/>') +
                  '</td>',
              );
            }
            html.push('</tr>');
          }
          return '<table><tbody>' + html.join('') + '</tbody></table>';
        }
        if (!opt) {
          opt = utils.extend(
            {},
            { numCols: this.options.defaultCols, numRows: this.options.defaultRows, tdvalign: this.options.tdvalign },
          );
        }
        var me = this;
        var range = this.selection.getRange(),
          start = range.startContainer,
          firstParentBlock =
            domUtils.findParent(
              start,
              function (node) {
                return domUtils.isBlockElm(node);
              },
              true,
            ) || me.body;
        var defaultValue = getDefaultValue(me),
          tableWidth = firstParentBlock.offsetWidth,
          tdWidth = Math.floor(tableWidth / opt.numCols - defaultValue.tdPadding * 2 - defaultValue.tdBorder);
        !opt.tdvalign && (opt.tdvalign = me.options.tdvalign);
        me.execCommand('inserthtml', createTable(opt, tdWidth));
      },
    };
    UE.commands['insertparagraphbeforetable'] = {
      queryCommandState: function () {
        return getTableItemsByRange(this).cell ? 0 : -1;
      },
      execCommand: function () {
        var table = getTableItemsByRange(this).table;
        if (table) {
          var p = this.document.createElement('p');
          p.innerHTML = browser.ie ? '&nbsp;' : '<br />';
          table.parentNode.insertBefore(p, table);
          this.selection.getRange().setStart(p, 0).setCursor();
        }
      },
    };
    UE.commands['deletetable'] = {
      queryCommandState: function () {
        var rng = this.selection.getRange();
        return domUtils.findParentByTagName(rng.startContainer, 'table', true) ? 0 : -1;
      },
      execCommand: function (cmd, table) {
        var rng = this.selection.getRange();
        table = table || domUtils.findParentByTagName(rng.startContainer, 'table', true);
        if (table) {
          var next = table.nextSibling;
          if (!next) {
            next = domUtils.createElement(this.document, 'p', { innerHTML: browser.ie ? domUtils.fillChar : '<br/>' });
            table.parentNode.insertBefore(next, table);
          }
          domUtils.remove(table);
          rng = this.selection.getRange();
          if (next.nodeType == 3) {
            rng.setStartBefore(next);
          } else {
            rng.setStart(next, 0);
          }
          rng.setCursor(false, true);
          this.fireEvent('tablehasdeleted');
        }
      },
    };
    UE.commands['cellalign'] = {
      queryCommandState: function () {
        return getSelectedArr(this).length ? 0 : -1;
      },
      execCommand: function (cmd, align) {
        var selectedTds = getSelectedArr(this);
        if (selectedTds.length) {
          for (var i = 0, ci; (ci = selectedTds[i++]); ) {
            ci.setAttribute('align', align);
          }
        }
      },
    };
    UE.commands['cellvalign'] = {
      queryCommandState: function () {
        return getSelectedArr(this).length ? 0 : -1;
      },
      execCommand: function (cmd, valign) {
        var selectedTds = getSelectedArr(this);
        if (selectedTds.length) {
          for (var i = 0, ci; (ci = selectedTds[i++]); ) {
            ci.setAttribute('vAlign', valign);
          }
        }
      },
    };
    UE.commands['insertcaption'] = {
      queryCommandState: function () {
        var table = getTableItemsByRange(this).table;
        if (table) {
          return table.getElementsByTagName('caption').length == 0 ? 1 : -1;
        }
        return -1;
      },
      execCommand: function () {
        var table = getTableItemsByRange(this).table;
        if (table) {
          var caption = this.document.createElement('caption');
          caption.innerHTML = browser.ie ? domUtils.fillChar : '<br/>';
          table.insertBefore(caption, table.firstChild);
          var range = this.selection.getRange();
          range.setStart(caption, 0).setCursor();
        }
      },
    };
    UE.commands['deletecaption'] = {
      queryCommandState: function () {
        var rng = this.selection.getRange(),
          table = domUtils.findParentByTagName(rng.startContainer, 'table');
        if (table) {
          return table.getElementsByTagName('caption').length == 0 ? -1 : 1;
        }
        return -1;
      },
      execCommand: function () {
        var rng = this.selection.getRange(),
          table = domUtils.findParentByTagName(rng.startContainer, 'table');
        if (table) {
          domUtils.remove(table.getElementsByTagName('caption')[0]);
          var range = this.selection.getRange();
          range.setStart(table.rows[0].cells[0], 0).setCursor();
        }
      },
    };
    UE.commands['inserttitle'] = {
      queryCommandState: function () {
        var table = getTableItemsByRange(this).table;
        if (table) {
          var firstRow = table.rows[0];
          return firstRow.cells[firstRow.cells.length - 1].tagName.toLowerCase() != 'th' ? 0 : -1;
        }
        return -1;
      },
      execCommand: function () {
        var table = getTableItemsByRange(this).table;
        if (table) {
          getUETable(table).insertRow(0, 'th');
        }
        var th = table.getElementsByTagName('th')[0];
        this.selection.getRange().setStart(th, 0).setCursor(false, true);
      },
    };
    UE.commands['deletetitle'] = {
      queryCommandState: function () {
        var table = getTableItemsByRange(this).table;
        if (table) {
          var firstRow = table.rows[0];
          return firstRow.cells[firstRow.cells.length - 1].tagName.toLowerCase() == 'th' ? 0 : -1;
        }
        return -1;
      },
      execCommand: function () {
        var table = getTableItemsByRange(this).table;
        if (table) {
          domUtils.remove(table.rows[0]);
        }
        var td = table.getElementsByTagName('td')[0];
        this.selection.getRange().setStart(td, 0).setCursor(false, true);
      },
    };
    UE.commands['inserttitlecol'] = {
      queryCommandState: function () {
        var table = getTableItemsByRange(this).table;
        if (table) {
          var lastRow = table.rows[table.rows.length - 1];
          return lastRow.getElementsByTagName('th').length ? -1 : 0;
        }
        return -1;
      },
      execCommand: function (cmd) {
        var table = getTableItemsByRange(this).table;
        if (table) {
          getUETable(table).insertCol(0, 'th');
        }
        resetTdWidth(table, this);
        var th = table.getElementsByTagName('th')[0];
        this.selection.getRange().setStart(th, 0).setCursor(false, true);
      },
    };
    UE.commands['deletetitlecol'] = {
      queryCommandState: function () {
        var table = getTableItemsByRange(this).table;
        if (table) {
          var lastRow = table.rows[table.rows.length - 1];
          return lastRow.getElementsByTagName('th').length ? 0 : -1;
        }
        return -1;
      },
      execCommand: function () {
        var table = getTableItemsByRange(this).table;
        if (table) {
          for (var i = 0; i < table.rows.length; i++) {
            domUtils.remove(table.rows[i].children[0]);
          }
        }
        resetTdWidth(table, this);
        var td = table.getElementsByTagName('td')[0];
        this.selection.getRange().setStart(td, 0).setCursor(false, true);
      },
    };
    UE.commands['mergeright'] = {
      queryCommandState: function (cmd) {
        var tableItems = getTableItemsByRange(this),
          table = tableItems.table,
          cell = tableItems.cell;
        if (!table || !cell) return -1;
        var ut = getUETable(table);
        if (ut.selectedTds.length) return -1;
        var cellInfo = ut.getCellInfo(cell),
          rightColIndex = cellInfo.colIndex + cellInfo.colSpan;
        if (rightColIndex >= ut.colsNum) return -1;
        var rightCellInfo = ut.indexTable[cellInfo.rowIndex][rightColIndex],
          rightCell = table.rows[rightCellInfo.rowIndex].cells[rightCellInfo.cellIndex];
        if (!rightCell || cell.tagName != rightCell.tagName) return -1;
        return rightCellInfo.rowIndex == cellInfo.rowIndex && rightCellInfo.rowSpan == cellInfo.rowSpan ? 0 : -1;
      },
      execCommand: function (cmd) {
        var rng = this.selection.getRange(),
          bk = rng.createBookmark(true);
        var cell = getTableItemsByRange(this).cell,
          ut = getUETable(cell);
        ut.mergeRight(cell);
        rng.moveToBookmark(bk).select();
      },
    };
    UE.commands['mergedown'] = {
      queryCommandState: function (cmd) {
        var tableItems = getTableItemsByRange(this),
          table = tableItems.table,
          cell = tableItems.cell;
        if (!table || !cell) return -1;
        var ut = getUETable(table);
        if (ut.selectedTds.length) return -1;
        var cellInfo = ut.getCellInfo(cell),
          downRowIndex = cellInfo.rowIndex + cellInfo.rowSpan;
        if (downRowIndex >= ut.rowsNum) return -1;
        var downCellInfo = ut.indexTable[downRowIndex][cellInfo.colIndex],
          downCell = table.rows[downCellInfo.rowIndex].cells[downCellInfo.cellIndex];
        if (!downCell || cell.tagName != downCell.tagName) return -1;
        return downCellInfo.colIndex == cellInfo.colIndex && downCellInfo.colSpan == cellInfo.colSpan ? 0 : -1;
      },
      execCommand: function () {
        var rng = this.selection.getRange(),
          bk = rng.createBookmark(true);
        var cell = getTableItemsByRange(this).cell,
          ut = getUETable(cell);
        ut.mergeDown(cell);
        rng.moveToBookmark(bk).select();
      },
    };
    UE.commands['mergecells'] = {
      queryCommandState: function () {
        return getUETableBySelected(this) ? 0 : -1;
      },
      execCommand: function () {
        var ut = getUETableBySelected(this);
        if (ut && ut.selectedTds.length) {
          var cell = ut.selectedTds[0];
          ut.mergeRange();
          var rng = this.selection.getRange();
          if (domUtils.isEmptyBlock(cell)) {
            rng.setStart(cell, 0).collapse(true);
          } else {
            rng.selectNodeContents(cell);
          }
          rng.select();
        }
      },
    };
    UE.commands['insertrow'] = {
      queryCommandState: function () {
        var tableItems = getTableItemsByRange(this),
          cell = tableItems.cell;
        return cell &&
          (cell.tagName == 'TD' || (cell.tagName == 'TH' && tableItems.tr !== tableItems.table.rows[0])) &&
          getUETable(tableItems.table).rowsNum < this.options.maxRowNum
          ? 0
          : -1;
      },
      execCommand: function () {
        var rng = this.selection.getRange(),
          bk = rng.createBookmark(true);
        var tableItems = getTableItemsByRange(this),
          cell = tableItems.cell,
          table = tableItems.table,
          ut = getUETable(table),
          cellInfo = ut.getCellInfo(cell);
        if (!ut.selectedTds.length) {
          ut.insertRow(cellInfo.rowIndex, cell);
        } else {
          var range = ut.cellsRange;
          for (var i = 0, len = range.endRowIndex - range.beginRowIndex + 1; i < len; i++) {
            ut.insertRow(range.beginRowIndex, cell);
          }
        }
        rng.moveToBookmark(bk).select();
        if (table.getAttribute('interlaced') === 'enabled') this.fireEvent('interlacetable', table);
      },
    };
    UE.commands['insertrownext'] = {
      queryCommandState: function () {
        var tableItems = getTableItemsByRange(this),
          cell = tableItems.cell;
        return cell && cell.tagName == 'TD' && getUETable(tableItems.table).rowsNum < this.options.maxRowNum ? 0 : -1;
      },
      execCommand: function () {
        var rng = this.selection.getRange(),
          bk = rng.createBookmark(true);
        var tableItems = getTableItemsByRange(this),
          cell = tableItems.cell,
          table = tableItems.table,
          ut = getUETable(table),
          cellInfo = ut.getCellInfo(cell);
        if (!ut.selectedTds.length) {
          ut.insertRow(cellInfo.rowIndex + cellInfo.rowSpan, cell);
        } else {
          var range = ut.cellsRange;
          for (var i = 0, len = range.endRowIndex - range.beginRowIndex + 1; i < len; i++) {
            ut.insertRow(range.endRowIndex + 1, cell);
          }
        }
        rng.moveToBookmark(bk).select();
        if (table.getAttribute('interlaced') === 'enabled') this.fireEvent('interlacetable', table);
      },
    };
    UE.commands['deleterow'] = {
      queryCommandState: function () {
        var tableItems = getTableItemsByRange(this);
        return tableItems.cell ? 0 : -1;
      },
      execCommand: function () {
        var cell = getTableItemsByRange(this).cell,
          ut = getUETable(cell),
          cellsRange = ut.cellsRange,
          cellInfo = ut.getCellInfo(cell),
          preCell = ut.getVSideCell(cell),
          nextCell = ut.getVSideCell(cell, true),
          rng = this.selection.getRange();
        if (utils.isEmptyObject(cellsRange)) {
          ut.deleteRow(cellInfo.rowIndex);
        } else {
          for (var i = cellsRange.beginRowIndex; i < cellsRange.endRowIndex + 1; i++) {
            ut.deleteRow(cellsRange.beginRowIndex);
          }
        }
        var table = ut.table;
        if (!table.getElementsByTagName('td').length) {
          var nextSibling = table.nextSibling;
          domUtils.remove(table);
          if (nextSibling) {
            rng.setStart(nextSibling, 0).setCursor(false, true);
          }
        } else {
          if (cellInfo.rowSpan == 1 || cellInfo.rowSpan == cellsRange.endRowIndex - cellsRange.beginRowIndex + 1) {
            if (nextCell || preCell) rng.selectNodeContents(nextCell || preCell).setCursor(false, true);
          } else {
            var newCell = ut.getCell(cellInfo.rowIndex, ut.indexTable[cellInfo.rowIndex][cellInfo.colIndex].cellIndex);
            if (newCell) rng.selectNodeContents(newCell).setCursor(false, true);
          }
        }
        if (table.getAttribute('interlaced') === 'enabled') this.fireEvent('interlacetable', table);
      },
    };
    UE.commands['insertcol'] = {
      queryCommandState: function (cmd) {
        var tableItems = getTableItemsByRange(this),
          cell = tableItems.cell;
        return cell &&
          (cell.tagName == 'TD' || (cell.tagName == 'TH' && cell !== tableItems.tr.cells[0])) &&
          getUETable(tableItems.table).colsNum < this.options.maxColNum
          ? 0
          : -1;
      },
      execCommand: function (cmd) {
        var rng = this.selection.getRange(),
          bk = rng.createBookmark(true);
        if (this.queryCommandState(cmd) == -1) return;
        var cell = getTableItemsByRange(this).cell,
          ut = getUETable(cell),
          cellInfo = ut.getCellInfo(cell);
        if (!ut.selectedTds.length) {
          ut.insertCol(cellInfo.colIndex, cell);
        } else {
          var range = ut.cellsRange;
          for (var i = 0, len = range.endColIndex - range.beginColIndex + 1; i < len; i++) {
            ut.insertCol(range.beginColIndex, cell);
          }
        }
        rng.moveToBookmark(bk).select(true);
      },
    };
    UE.commands['insertcolnext'] = {
      queryCommandState: function () {
        var tableItems = getTableItemsByRange(this),
          cell = tableItems.cell;
        return cell && getUETable(tableItems.table).colsNum < this.options.maxColNum ? 0 : -1;
      },
      execCommand: function () {
        var rng = this.selection.getRange(),
          bk = rng.createBookmark(true);
        var cell = getTableItemsByRange(this).cell,
          ut = getUETable(cell),
          cellInfo = ut.getCellInfo(cell);
        if (!ut.selectedTds.length) {
          ut.insertCol(cellInfo.colIndex + cellInfo.colSpan, cell);
        } else {
          var range = ut.cellsRange;
          for (var i = 0, len = range.endColIndex - range.beginColIndex + 1; i < len; i++) {
            ut.insertCol(range.endColIndex + 1, cell);
          }
        }
        rng.moveToBookmark(bk).select();
      },
    };
    UE.commands['deletecol'] = {
      queryCommandState: function () {
        var tableItems = getTableItemsByRange(this);
        return tableItems.cell ? 0 : -1;
      },
      execCommand: function () {
        var cell = getTableItemsByRange(this).cell,
          ut = getUETable(cell),
          range = ut.cellsRange,
          cellInfo = ut.getCellInfo(cell),
          preCell = ut.getHSideCell(cell),
          nextCell = ut.getHSideCell(cell, true);
        if (utils.isEmptyObject(range)) {
          ut.deleteCol(cellInfo.colIndex);
        } else {
          for (var i = range.beginColIndex; i < range.endColIndex + 1; i++) {
            ut.deleteCol(range.beginColIndex);
          }
        }
        var table = ut.table,
          rng = this.selection.getRange();
        if (!table.getElementsByTagName('td').length) {
          var nextSibling = table.nextSibling;
          domUtils.remove(table);
          if (nextSibling) {
            rng.setStart(nextSibling, 0).setCursor(false, true);
          }
        } else {
          if (domUtils.inDoc(cell, this.document)) {
            rng.setStart(cell, 0).setCursor(false, true);
          } else {
            if (nextCell && domUtils.inDoc(nextCell, this.document)) {
              rng.selectNodeContents(nextCell).setCursor(false, true);
            } else {
              if (preCell && domUtils.inDoc(preCell, this.document)) {
                rng.selectNodeContents(preCell).setCursor(true, true);
              }
            }
          }
        }
      },
    };
    UE.commands['splittocells'] = {
      queryCommandState: function () {
        var tableItems = getTableItemsByRange(this),
          cell = tableItems.cell;
        if (!cell) return -1;
        var ut = getUETable(tableItems.table);
        if (ut.selectedTds.length > 0) return -1;
        return cell && (cell.colSpan > 1 || cell.rowSpan > 1) ? 0 : -1;
      },
      execCommand: function () {
        var rng = this.selection.getRange(),
          bk = rng.createBookmark(true);
        var cell = getTableItemsByRange(this).cell,
          ut = getUETable(cell);
        ut.splitToCells(cell);
        rng.moveToBookmark(bk).select();
      },
    };
    UE.commands['splittorows'] = {
      queryCommandState: function () {
        var tableItems = getTableItemsByRange(this),
          cell = tableItems.cell;
        if (!cell) return -1;
        var ut = getUETable(tableItems.table);
        if (ut.selectedTds.length > 0) return -1;
        return cell && cell.rowSpan > 1 ? 0 : -1;
      },
      execCommand: function () {
        var rng = this.selection.getRange(),
          bk = rng.createBookmark(true);
        var cell = getTableItemsByRange(this).cell,
          ut = getUETable(cell);
        ut.splitToRows(cell);
        rng.moveToBookmark(bk).select();
      },
    };
    UE.commands['splittocols'] = {
      queryCommandState: function () {
        var tableItems = getTableItemsByRange(this),
          cell = tableItems.cell;
        if (!cell) return -1;
        var ut = getUETable(tableItems.table);
        if (ut.selectedTds.length > 0) return -1;
        return cell && cell.colSpan > 1 ? 0 : -1;
      },
      execCommand: function () {
        var rng = this.selection.getRange(),
          bk = rng.createBookmark(true);
        var cell = getTableItemsByRange(this).cell,
          ut = getUETable(cell);
        ut.splitToCols(cell);
        rng.moveToBookmark(bk).select();
      },
    };
    UE.commands['adaptbytext'] = UE.commands['adaptbywindow'] = {
      queryCommandState: function () {
        return getTableItemsByRange(this).table ? 0 : -1;
      },
      execCommand: function (cmd) {
        var tableItems = getTableItemsByRange(this),
          table = tableItems.table;
        if (table) {
          if (cmd == 'adaptbywindow') {
            resetTdWidth(table, this);
          } else {
            var cells = domUtils.getElementsByTagName(table, 'td th');
            utils.each(cells, function (cell) {
              cell.removeAttribute('width');
            });
            table.removeAttribute('width');
          }
        }
      },
    };
    UE.commands['averagedistributecol'] = {
      queryCommandState: function () {
        var ut = getUETableBySelected(this);
        if (!ut) return -1;
        return ut.isFullRow() || ut.isFullCol() ? 0 : -1;
      },
      execCommand: function (cmd) {
        var me = this,
          ut = getUETableBySelected(me);
        function getAverageWidth() {
          var tb = ut.table,
            averageWidth,
            sumWidth = 0,
            colsNum = 0,
            tbAttr = getDefaultValue(me, tb);
          if (ut.isFullRow()) {
            sumWidth = tb.offsetWidth;
            colsNum = ut.colsNum;
          } else {
            var begin = ut.cellsRange.beginColIndex,
              end = ut.cellsRange.endColIndex,
              node;
            for (var i = begin; i <= end; ) {
              node = ut.selectedTds[i];
              sumWidth += node.offsetWidth;
              i += node.colSpan;
              colsNum += 1;
            }
          }
          averageWidth = Math.ceil(sumWidth / colsNum) - tbAttr.tdBorder * 2 - tbAttr.tdPadding * 2;
          return averageWidth;
        }
        function setAverageWidth(averageWidth) {
          utils.each(domUtils.getElementsByTagName(ut.table, 'th'), function (node) {
            node.setAttribute('width', '');
          });
          var cells = ut.isFullRow() ? domUtils.getElementsByTagName(ut.table, 'td') : ut.selectedTds;
          utils.each(cells, function (node) {
            if (node.colSpan == 1) {
              node.setAttribute('width', averageWidth);
            }
          });
        }
        if (ut && ut.selectedTds.length) {
          setAverageWidth(getAverageWidth());
        }
      },
    };
    UE.commands['averagedistributerow'] = {
      queryCommandState: function () {
        var ut = getUETableBySelected(this);
        if (!ut) return -1;
        if (ut.selectedTds && /th/gi.test(ut.selectedTds[0].tagName)) return -1;
        return ut.isFullRow() || ut.isFullCol() ? 0 : -1;
      },
      execCommand: function (cmd) {
        var me = this,
          ut = getUETableBySelected(me);
        function getAverageHeight() {
          var averageHeight,
            rowNum,
            sumHeight = 0,
            tb = ut.table,
            tbAttr = getDefaultValue(me, tb),
            tdpadding = parseInt(domUtils.getComputedStyle(tb.getElementsByTagName('td')[0], 'padding-top'));
          if (ut.isFullCol()) {
            var captionArr = domUtils.getElementsByTagName(tb, 'caption'),
              thArr = domUtils.getElementsByTagName(tb, 'th'),
              captionHeight,
              thHeight;
            if (captionArr.length > 0) {
              captionHeight = captionArr[0].offsetHeight;
            }
            if (thArr.length > 0) {
              thHeight = thArr[0].offsetHeight;
            }
            sumHeight = tb.offsetHeight - (captionHeight || 0) - (thHeight || 0);
            rowNum = thArr.length == 0 ? ut.rowsNum : ut.rowsNum - 1;
          } else {
            var begin = ut.cellsRange.beginRowIndex,
              end = ut.cellsRange.endRowIndex,
              count = 0,
              trs = domUtils.getElementsByTagName(tb, 'tr');
            for (var i = begin; i <= end; i++) {
              sumHeight += trs[i].offsetHeight;
              count += 1;
            }
            rowNum = count;
          }
          if (browser.ie && browser.version < 9) {
            averageHeight = Math.ceil(sumHeight / rowNum);
          } else {
            averageHeight = Math.ceil(sumHeight / rowNum) - tbAttr.tdBorder * 2 - tdpadding * 2;
          }
          return averageHeight;
        }
        function setAverageHeight(averageHeight) {
          var cells = ut.isFullCol() ? domUtils.getElementsByTagName(ut.table, 'td') : ut.selectedTds;
          utils.each(cells, function (node) {
            if (node.rowSpan == 1) {
              node.setAttribute('height', averageHeight);
            }
          });
        }
        if (ut && ut.selectedTds.length) {
          setAverageHeight(getAverageHeight());
        }
      },
    };
    UE.commands['cellalignment'] = {
      queryCommandState: function () {
        return getTableItemsByRange(this).table ? 0 : -1;
      },
      execCommand: function (cmd, data) {
        var me = this,
          ut = getUETableBySelected(me);
        if (!ut) {
          var start = me.selection.getStart(),
            cell = start && domUtils.findParentByTagName(start, ['td', 'th', 'caption'], true);
          if (!/caption/gi.test(cell.tagName)) {
            domUtils.setAttributes(cell, data);
          } else {
            cell.style.textAlign = data.align;
            cell.style.verticalAlign = data.vAlign;
          }
          me.selection.getRange().setCursor(true);
        } else {
          utils.each(ut.selectedTds, function (cell) {
            domUtils.setAttributes(cell, data);
          });
        }
      },
      queryCommandValue: function (cmd) {
        var activeMenuCell = getTableItemsByRange(this).cell;
        if (!activeMenuCell) {
          activeMenuCell = getSelectedArr(this)[0];
        }
        if (!activeMenuCell) {
          return null;
        } else {
          var cells = UE.UETable.getUETable(activeMenuCell).selectedTds;
          !cells.length && (cells = activeMenuCell);
          return UE.UETable.getTableCellAlignState(cells);
        }
      },
    };
    UE.commands['tablealignment'] = {
      queryCommandState: function () {
        if (browser.ie && browser.version < 8) {
          return -1;
        }
        return getTableItemsByRange(this).table ? 0 : -1;
      },
      execCommand: function (cmd, value) {
        var me = this,
          start = me.selection.getStart(),
          table = start && domUtils.findParentByTagName(start, ['table'], true);
        if (table) {
          table.setAttribute('align', value);
        }
      },
    };
    UE.commands['edittable'] = {
      queryCommandState: function () {
        return getTableItemsByRange(this).table ? 0 : -1;
      },
      execCommand: function (cmd, color) {
        var rng = this.selection.getRange(),
          table = domUtils.findParentByTagName(rng.startContainer, 'table');
        if (table) {
          var arr = domUtils
            .getElementsByTagName(table, 'td')
            .concat(domUtils.getElementsByTagName(table, 'th'), domUtils.getElementsByTagName(table, 'caption'));
          utils.each(arr, function (node) {
            node.style.borderColor = color;
          });
        }
      },
    };
    UE.commands['edittd'] = {
      queryCommandState: function () {
        return getTableItemsByRange(this).table ? 0 : -1;
      },
      execCommand: function (cmd, bkColor) {
        var me = this,
          ut = getUETableBySelected(me);
        if (!ut) {
          var start = me.selection.getStart(),
            cell = start && domUtils.findParentByTagName(start, ['td', 'th', 'caption'], true);
          if (cell) {
            cell.style.backgroundColor = bkColor;
          }
        } else {
          utils.each(ut.selectedTds, function (cell) {
            cell.style.backgroundColor = bkColor;
          });
        }
      },
    };
    UE.commands['settablebackground'] = {
      queryCommandState: function () {
        return getSelectedArr(this).length > 1 ? 0 : -1;
      },
      execCommand: function (cmd, value) {
        var cells, ut;
        cells = getSelectedArr(this);
        ut = getUETable(cells[0]);
        ut.setBackground(cells, value);
      },
    };
    UE.commands['cleartablebackground'] = {
      queryCommandState: function () {
        var cells = getSelectedArr(this);
        if (!cells.length) return -1;
        for (var i = 0, cell; (cell = cells[i++]); ) {
          if (cell.style.backgroundColor !== '') return 0;
        }
        return -1;
      },
      execCommand: function () {
        var cells = getSelectedArr(this),
          ut = getUETable(cells[0]);
        ut.removeBackground(cells);
      },
    };
    UE.commands['interlacetable'] = UE.commands['uninterlacetable'] = {
      queryCommandState: function (cmd) {
        var table = getTableItemsByRange(this).table;
        if (!table) return -1;
        var interlaced = table.getAttribute('interlaced');
        if (cmd == 'interlacetable') {
          return interlaced === 'enabled' ? -1 : 0;
        } else {
          return !interlaced || interlaced === 'disabled' ? -1 : 0;
        }
      },
      execCommand: function (cmd, classList) {
        var table = getTableItemsByRange(this).table;
        if (cmd == 'interlacetable') {
          table.setAttribute('interlaced', 'enabled');
          this.fireEvent('interlacetable', table, classList);
        } else {
          table.setAttribute('interlaced', 'disabled');
          this.fireEvent('uninterlacetable', table);
        }
      },
    };
    UE.commands['setbordervisible'] = {
      queryCommandState: function (cmd) {
        var table = getTableItemsByRange(this).table;
        if (!table) return -1;
        return 0;
      },
      execCommand: function () {
        var table = getTableItemsByRange(this).table;
        utils.each(domUtils.getElementsByTagName(table, 'td'), function (td) {
          td.style.borderWidth = '1px';
          td.style.borderStyle = 'solid';
        });
      },
    };
    function resetTdWidth(table, editor) {
      var tds = domUtils.getElementsByTagName(table, 'td th');
      utils.each(tds, function (td) {
        td.removeAttribute('width');
      });
      table.setAttribute('width', '100%');
      var tdsWidths = [];
      setTimeout(function () {
        utils.each(tds, function (td) {
          td.colSpan == 1 && tdsWidths.push(td.offsetWidth);
        });
        utils.each(tds, function (td, i) {
          td.colSpan == 1 && td.setAttribute('width', tdsWidths[i] + '');
        });
      }, 0);
    }
    function getTableWidth(editor, needIEHack, defaultValue) {
      var body = editor.body;
      return (
        body.offsetWidth -
        (needIEHack ? parseInt(domUtils.getComputedStyle(body, 'margin-left'), 10) * 2 : 0) -
        defaultValue.tableBorder * 2 -
        (editor.options.offsetWidth || 0)
      );
    }
    function getSelectedArr(editor) {
      var cell = getTableItemsByRange(editor).cell;
      if (cell) {
        var ut = getUETable(cell);
        return ut.selectedTds.length ? ut.selectedTds : [cell];
      } else {
        return [];
      }
    }
  })();
  UE.plugins['table'] = function () {
    var me = this,
      tabTimer = null,
      tableDragTimer = null,
      tableResizeTimer = null,
      cellMinWidth = 5,
      isInResizeBuffer = false,
      cellBorderWidth = 5,
      offsetOfTableCell = 10,
      singleClickState = 0,
      userActionStatus = null,
      dblclickTime = 200,
      UT = UE.UETable,
      getUETable = function (tdOrTable) {
        return UT.getUETable(tdOrTable);
      },
      getUETableBySelected = function (editor) {
        return UT.getUETableBySelected(editor);
      },
      getDefaultValue = function (editor, table) {
        return UT.getDefaultValue(editor, table);
      },
      removeSelectedClass = function (cells) {
        return UT.removeSelectedClass(cells);
      };
    function showError(e) {}
    me.ready(function () {
      var me = this;
      var orgGetText = me.selection.getText;
      me.selection.getText = function () {
        var table = getUETableBySelected(me);
        if (table) {
          var str = '';
          utils.each(table.selectedTds, function (td) {
            str += td[browser.ie ? 'innerText' : 'textContent'];
          });
          return str;
        } else {
          return orgGetText.call(me.selection);
        }
      };
    });
    var startTd = null,
      currentTd = null,
      onDrag = '',
      onBorder = false,
      dragButton = null,
      dragOver = false,
      dragLine = null,
      dragTd = null;
    var mousedown = false,
      needIEHack = true;
    me.setOpt({
      maxColNum: 20,
      maxRowNum: 100,
      defaultCols: 5,
      defaultRows: 5,
      tdvalign: 'top',
      cursorpath: me.options.UEDITOR_HOME_URL + 'themes/default/images/cursor_',
      tableDragable: false,
      classList: ['ue-table-interlace-color-single', 'ue-table-interlace-color-double'],
    });
    me.getUETable = getUETable;
    var commands = {
      deletetable: 1,
      inserttable: 1,
      cellvalign: 1,
      insertcaption: 1,
      deletecaption: 1,
      inserttitle: 1,
      deletetitle: 1,
      mergeright: 1,
      mergedown: 1,
      mergecells: 1,
      insertrow: 1,
      insertrownext: 1,
      deleterow: 1,
      insertcol: 1,
      insertcolnext: 1,
      deletecol: 1,
      splittocells: 1,
      splittorows: 1,
      splittocols: 1,
      adaptbytext: 1,
      adaptbywindow: 1,
      adaptbycustomer: 1,
      insertparagraph: 1,
      insertparagraphbeforetable: 1,
      averagedistributecol: 1,
      averagedistributerow: 1,
    };
    me.ready(function () {
      utils.cssRule(
        'table',
        '.selectTdClass{background-color:#edf5fa !important}' +
          'table.noBorderTable td,table.noBorderTable th,table.noBorderTable caption{border:1px dashed #ddd !important}' +
          'table{margin-bottom:10px;border-collapse:collapse;display:table;}' +
          'td,th{padding: 5px 10px;border: 1px solid #DDD;}' +
          'caption{border:1px dashed #DDD;border-bottom:0;padding:3px;text-align:center;}' +
          'th{border-top:1px solid #BBB;background-color:#F7F7F7;}' +
          'table tr.firstRow th{border-top-width:2px;}' +
          '.ue-table-interlace-color-single{ background-color: #fcfcfc; } .ue-table-interlace-color-double{ background-color: #f7faff; }' +
          'td p{margin:0;padding:0;}',
        me.document,
      );
      var tableCopyList, isFullCol, isFullRow;
      me.addListener('keydown', function (cmd, evt) {
        var me = this;
        var keyCode = evt.keyCode || evt.which;
        if (keyCode == 8) {
          var ut = getUETableBySelected(me);
          if (ut && ut.selectedTds.length) {
            if (ut.isFullCol()) {
              me.execCommand('deletecol');
            } else if (ut.isFullRow()) {
              me.execCommand('deleterow');
            } else {
              me.fireEvent('delcells');
            }
            domUtils.preventDefault(evt);
          }
          var caption = domUtils.findParentByTagName(me.selection.getStart(), 'caption', true),
            range = me.selection.getRange();
          if (range.collapsed && caption && isEmptyBlock(caption)) {
            me.fireEvent('saveScene');
            var table = caption.parentNode;
            domUtils.remove(caption);
            if (table) {
              range.setStart(table.rows[0].cells[0], 0).setCursor(false, true);
            }
            me.fireEvent('saveScene');
          }
        }
        if (keyCode == 46) {
          ut = getUETableBySelected(me);
          if (ut) {
            me.fireEvent('saveScene');
            for (var i = 0, ci; (ci = ut.selectedTds[i++]); ) {
              domUtils.fillNode(me.document, ci);
            }
            me.fireEvent('saveScene');
            domUtils.preventDefault(evt);
          }
        }
        if (keyCode == 13) {
          var rng = me.selection.getRange(),
            caption = domUtils.findParentByTagName(rng.startContainer, 'caption', true);
          if (caption) {
            var table = domUtils.findParentByTagName(caption, 'table');
            if (!rng.collapsed) {
              rng.deleteContents();
              me.fireEvent('saveScene');
            } else {
              if (caption) {
                rng.setStart(table.rows[0].cells[0], 0).setCursor(false, true);
              }
            }
            domUtils.preventDefault(evt);
            return;
          }
          if (rng.collapsed) {
            var table = domUtils.findParentByTagName(rng.startContainer, 'table');
            if (table) {
              var cell = table.rows[0].cells[0],
                start = domUtils.findParentByTagName(me.selection.getStart(), ['td', 'th'], true),
                preNode = table.previousSibling;
              if (
                cell === start &&
                (!preNode || (preNode.nodeType == 1 && preNode.tagName == 'TABLE')) &&
                domUtils.isStartInblock(rng)
              ) {
                var first = domUtils.findParent(
                  me.selection.getStart(),
                  function (n) {
                    return domUtils.isBlockElm(n);
                  },
                  true,
                );
                if (first && (/t(h|d)/i.test(first.tagName) || first === start.firstChild)) {
                  me.execCommand('insertparagraphbeforetable');
                  domUtils.preventDefault(evt);
                }
              }
            }
          }
        }
        if ((evt.ctrlKey || evt.metaKey) && evt.keyCode == '67') {
          tableCopyList = null;
          var ut = getUETableBySelected(me);
          if (ut) {
            var tds = ut.selectedTds;
            isFullCol = ut.isFullCol();
            isFullRow = ut.isFullRow();
            tableCopyList = [[ut.cloneCell(tds[0], null, true)]];
            for (var i = 1, ci; (ci = tds[i]); i++) {
              if (ci.parentNode !== tds[i - 1].parentNode) {
                tableCopyList.push([ut.cloneCell(ci, null, true)]);
              } else {
                tableCopyList[tableCopyList.length - 1].push(ut.cloneCell(ci, null, true));
              }
            }
          }
        }
      });
      me.addListener('tablehasdeleted', function () {
        toggleDraggableState(this, false, '', null);
        if (dragButton) domUtils.remove(dragButton);
      });
      me.addListener('beforepaste', function (cmd, html) {
        var me = this;
        var rng = me.selection.getRange();
        if (domUtils.findParentByTagName(rng.startContainer, 'caption', true)) {
          var div = me.document.createElement('div');
          div.innerHTML = html.html;
          html.html = div[browser.ie9below ? 'innerText' : 'textContent'];
          return;
        }
        var table = getUETableBySelected(me);
        if (tableCopyList) {
          me.fireEvent('saveScene');
          var rng = me.selection.getRange();
          var td = domUtils.findParentByTagName(rng.startContainer, ['td', 'th'], true),
            tmpNode,
            preNode;
          if (td) {
            var ut = getUETable(td);
            if (isFullRow) {
              var rowIndex = ut.getCellInfo(td).rowIndex;
              if (td.tagName == 'TH') {
                rowIndex++;
              }
              for (var i = 0, ci; (ci = tableCopyList[i++]); ) {
                var tr = ut.insertRow(rowIndex++, 'td');
                for (var j = 0, cj; (cj = ci[j]); j++) {
                  var cell = tr.cells[j];
                  if (!cell) {
                    cell = tr.insertCell(j);
                  }
                  cell.innerHTML = cj.innerHTML;
                  cj.getAttribute('width') && cell.setAttribute('width', cj.getAttribute('width'));
                  cj.getAttribute('vAlign') && cell.setAttribute('vAlign', cj.getAttribute('vAlign'));
                  cj.getAttribute('align') && cell.setAttribute('align', cj.getAttribute('align'));
                  cj.style.cssText && (cell.style.cssText = cj.style.cssText);
                }
                for (var j = 0, cj; (cj = tr.cells[j]); j++) {
                  if (!ci[j]) break;
                  cj.innerHTML = ci[j].innerHTML;
                  ci[j].getAttribute('width') && cj.setAttribute('width', ci[j].getAttribute('width'));
                  ci[j].getAttribute('vAlign') && cj.setAttribute('vAlign', ci[j].getAttribute('vAlign'));
                  ci[j].getAttribute('align') && cj.setAttribute('align', ci[j].getAttribute('align'));
                  ci[j].style.cssText && (cj.style.cssText = ci[j].style.cssText);
                }
              }
            } else {
              if (isFullCol) {
                cellInfo = ut.getCellInfo(td);
                var maxColNum = 0;
                for (var j = 0, ci = tableCopyList[0], cj; (cj = ci[j++]); ) {
                  maxColNum += cj.colSpan || 1;
                }
                me.__hasEnterExecCommand = true;
                for (i = 0; i < maxColNum; i++) {
                  me.execCommand('insertcol');
                }
                me.__hasEnterExecCommand = false;
                td = ut.table.rows[0].cells[cellInfo.cellIndex];
                if (td.tagName == 'TH') {
                  td = ut.table.rows[1].cells[cellInfo.cellIndex];
                }
              }
              for (var i = 0, ci; (ci = tableCopyList[i++]); ) {
                tmpNode = td;
                for (var j = 0, cj; (cj = ci[j++]); ) {
                  if (td) {
                    td.innerHTML = cj.innerHTML;
                    cj.getAttribute('width') && td.setAttribute('width', cj.getAttribute('width'));
                    cj.getAttribute('vAlign') && td.setAttribute('vAlign', cj.getAttribute('vAlign'));
                    cj.getAttribute('align') && td.setAttribute('align', cj.getAttribute('align'));
                    cj.style.cssText && (td.style.cssText = cj.style.cssText);
                    preNode = td;
                    td = td.nextSibling;
                  } else {
                    var cloneTd = cj.cloneNode(true);
                    domUtils.removeAttributes(cloneTd, ['class', 'rowSpan', 'colSpan']);
                    preNode.parentNode.appendChild(cloneTd);
                  }
                }
                td = ut.getNextCell(tmpNode, true, true);
                if (!tableCopyList[i]) break;
                if (!td) {
                  var cellInfo = ut.getCellInfo(tmpNode);
                  ut.table.insertRow(ut.table.rows.length);
                  ut.update();
                  td = ut.getVSideCell(tmpNode, true);
                }
              }
            }
            ut.update();
          } else {
            table = me.document.createElement('table');
            for (var i = 0, ci; (ci = tableCopyList[i++]); ) {
              var tr = table.insertRow(table.rows.length);
              for (var j = 0, cj; (cj = ci[j++]); ) {
                cloneTd = UT.cloneCell(cj, null, true);
                domUtils.removeAttributes(cloneTd, ['class']);
                tr.appendChild(cloneTd);
              }
              if (j == 2 && cloneTd.rowSpan > 1) {
                cloneTd.rowSpan = 1;
              }
            }
            var defaultValue = getDefaultValue(me),
              width =
                me.body.offsetWidth -
                (needIEHack ? parseInt(domUtils.getComputedStyle(me.body, 'margin-left'), 10) * 2 : 0) -
                defaultValue.tableBorder * 2 -
                (me.options.offsetWidth || 0);
            me.execCommand(
              'insertHTML',
              '<table  ' +
                (isFullCol && isFullRow ? 'width="' + width + '"' : '') +
                '>' +
                table.innerHTML.replace(/>\s*</g, '><').replace(/\bth\b/gi, 'td') +
                '</table>',
            );
          }
          me.fireEvent('contentchange');
          me.fireEvent('saveScene');
          html.html = '';
          return true;
        } else {
          var div = me.document.createElement('div'),
            tables;
          div.innerHTML = html.html;
          tables = div.getElementsByTagName('table');
          if (domUtils.findParentByTagName(me.selection.getStart(), 'table')) {
            utils.each(tables, function (t) {
              domUtils.remove(t);
            });
            if (domUtils.findParentByTagName(me.selection.getStart(), 'caption', true)) {
              div.innerHTML = div[browser.ie ? 'innerText' : 'textContent'];
            }
          } else {
            utils.each(tables, function (table) {
              removeStyleSize(table, true);
              domUtils.removeAttributes(table, ['style', 'border']);
              utils.each(domUtils.getElementsByTagName(table, 'td'), function (td) {
                if (isEmptyBlock(td)) {
                  domUtils.fillNode(me.document, td);
                }
                removeStyleSize(td, true);
              });
            });
          }
          html.html = div.innerHTML;
        }
      });
      me.addListener('afterpaste', function () {
        utils.each(domUtils.getElementsByTagName(me.body, 'table'), function (table) {
          if (table.offsetWidth > me.body.offsetWidth) {
            var defaultValue = getDefaultValue(me, table);
            table.style.width =
              me.body.offsetWidth -
              (needIEHack ? parseInt(domUtils.getComputedStyle(me.body, 'margin-left'), 10) * 2 : 0) -
              defaultValue.tableBorder * 2 -
              (me.options.offsetWidth || 0) +
              'px';
          }
        });
      });
      me.addListener('blur', function () {
        tableCopyList = null;
      });
      var timer;
      me.addListener('keydown', function () {
        clearTimeout(timer);
        timer = setTimeout(function () {
          var rng = me.selection.getRange(),
            cell = domUtils.findParentByTagName(rng.startContainer, ['th', 'td'], true);
          if (cell) {
            var table = cell.parentNode.parentNode.parentNode;
            if (table.offsetWidth > table.getAttribute('width')) {
              cell.style.wordBreak = 'break-all';
            }
          }
        }, 100);
      });
      me.addListener('selectionchange', function () {
        toggleDraggableState(me, false, '', null);
      });
      me.addListener('contentchange', function () {
        var me = this;
        hideDragLine(me);
        if (getUETableBySelected(me)) return;
        var rng = me.selection.getRange();
        var start = rng.startContainer;
        start = domUtils.findParentByTagName(start, ['td', 'th'], true);
        utils.each(domUtils.getElementsByTagName(me.document, 'table'), function (table) {
          if (me.fireEvent('excludetable', table) === true) return;
          table.ueTable = new UT(table);
          table.onmouseover = function () {
            me.fireEvent('tablemouseover', table);
          };
          table.onmousemove = function () {
            me.fireEvent('tablemousemove', table);
            me.options.tableDragable && toggleDragButton(true, this, me);
            utils.defer(function () {
              me.fireEvent('contentchange', 50);
            }, true);
          };
          table.onmouseout = function () {
            me.fireEvent('tablemouseout', table);
            toggleDraggableState(me, false, '', null);
            hideDragLine(me);
          };
          table.onclick = function (evt) {
            evt = me.window.event || evt;
            var target = getParentTdOrTh(evt.target || evt.srcElement);
            if (!target) return;
            var ut = getUETable(target),
              table = ut.table,
              cellInfo = ut.getCellInfo(target),
              cellsRange,
              rng = me.selection.getRange();
            if (inTableSide(table, target, evt, true)) {
              var endTdCol = ut.getCell(
                ut.indexTable[ut.rowsNum - 1][cellInfo.colIndex].rowIndex,
                ut.indexTable[ut.rowsNum - 1][cellInfo.colIndex].cellIndex,
              );
              if (evt.shiftKey && ut.selectedTds.length) {
                if (ut.selectedTds[0] !== endTdCol) {
                  cellsRange = ut.getCellsRange(ut.selectedTds[0], endTdCol);
                  ut.setSelected(cellsRange);
                } else {
                  rng && rng.selectNodeContents(endTdCol).select();
                }
              } else {
                if (target !== endTdCol) {
                  cellsRange = ut.getCellsRange(target, endTdCol);
                  ut.setSelected(cellsRange);
                } else {
                  rng && rng.selectNodeContents(endTdCol).select();
                }
              }
              return;
            }
            if (inTableSide(table, target, evt)) {
              var endTdRow = ut.getCell(
                ut.indexTable[cellInfo.rowIndex][ut.colsNum - 1].rowIndex,
                ut.indexTable[cellInfo.rowIndex][ut.colsNum - 1].cellIndex,
              );
              if (evt.shiftKey && ut.selectedTds.length) {
                if (ut.selectedTds[0] !== endTdRow) {
                  cellsRange = ut.getCellsRange(ut.selectedTds[0], endTdRow);
                  ut.setSelected(cellsRange);
                } else {
                  rng && rng.selectNodeContents(endTdRow).select();
                }
              } else {
                if (target !== endTdRow) {
                  cellsRange = ut.getCellsRange(target, endTdRow);
                  ut.setSelected(cellsRange);
                } else {
                  rng && rng.selectNodeContents(endTdRow).select();
                }
              }
            }
          };
        });
        switchBorderColor(me, true);
      });
      domUtils.on(me.document, 'mousemove', mouseMoveEvent);
      domUtils.on(me.document, 'mouseout', function (evt) {
        var target = evt.target || evt.srcElement;
        if (target.tagName == 'TABLE') {
          toggleDraggableState(me, false, '', null);
        }
      });
      me.addListener('interlacetable', function (type, table, classList) {
        if (!table) return;
        var me = this,
          rows = table.rows,
          len = rows.length,
          getClass = function (list, index, repeat) {
            return list[index] ? list[index] : repeat ? list[index % list.length] : '';
          };
        for (var i = 0; i < len; i++) {
          rows[i].className = getClass(classList || me.options.classList, i, true);
        }
      });
      me.addListener('uninterlacetable', function (type, table) {
        if (!table) return;
        var me = this,
          rows = table.rows,
          classList = me.options.classList,
          len = rows.length;
        for (var i = 0; i < len; i++) {
          domUtils.removeClasses(rows[i], classList);
        }
      });
      me.addListener('mousedown', mouseDownEvent);
      me.addListener('mouseup', mouseUpEvent);
      domUtils.on(me.body, 'dragstart', function (evt) {
        mouseUpEvent.call(me, 'dragstart', evt);
      });
      me.addOutputRule(function (root) {
        utils.each(root.getNodesByTagName('div'), function (n) {
          if (n.getAttr('id') == 'ue_tableDragLine') {
            n.parentNode.removeChild(n);
          }
        });
      });
      var currentRowIndex = 0;
      me.addListener('mousedown', function () {
        currentRowIndex = 0;
      });
      me.addListener('tabkeydown', function () {
        var range = this.selection.getRange(),
          common = range.getCommonAncestor(true, true),
          table = domUtils.findParentByTagName(common, 'table');
        if (table) {
          if (domUtils.findParentByTagName(common, 'caption', true)) {
            var cell = domUtils.getElementsByTagName(table, 'th td');
            if (cell && cell.length) {
              range.setStart(cell[0], 0).setCursor(false, true);
            }
          } else {
            var cell = domUtils.findParentByTagName(common, ['td', 'th'], true),
              ua = getUETable(cell);
            currentRowIndex = cell.rowSpan > 1 ? currentRowIndex : ua.getCellInfo(cell).rowIndex;
            var nextCell = ua.getTabNextCell(cell, currentRowIndex);
            if (nextCell) {
              if (isEmptyBlock(nextCell)) {
                range.setStart(nextCell, 0).setCursor(false, true);
              } else {
                range.selectNodeContents(nextCell).select();
              }
            } else {
              me.fireEvent('saveScene');
              me.__hasEnterExecCommand = true;
              this.execCommand('insertrownext');
              me.__hasEnterExecCommand = false;
              range = this.selection.getRange();
              range.setStart(table.rows[table.rows.length - 1].cells[0], 0).setCursor();
              me.fireEvent('saveScene');
            }
          }
          return true;
        }
      });
      browser.ie &&
        me.addListener('selectionchange', function () {
          toggleDraggableState(this, false, '', null);
        });
      me.addListener('keydown', function (type, evt) {
        var me = this;
        var keyCode = evt.keyCode || evt.which;
        if (keyCode == 8 || keyCode == 46) {
          return;
        }
        var notCtrlKey = !evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey;
        notCtrlKey && removeSelectedClass(domUtils.getElementsByTagName(me.body, 'td'));
        var ut = getUETableBySelected(me);
        if (!ut) return;
        notCtrlKey && ut.clearSelected();
      });
      me.addListener('beforegetcontent', function () {
        switchBorderColor(this, false);
        browser.ie &&
          utils.each(this.document.getElementsByTagName('caption'), function (ci) {
            if (domUtils.isEmptyNode(ci)) {
              ci.innerHTML = '&nbsp;';
            }
          });
      });
      me.addListener('aftergetcontent', function () {
        switchBorderColor(this, true);
      });
      me.addListener('getAllHtml', function () {
        removeSelectedClass(me.document.getElementsByTagName('td'));
      });
      me.addListener('fullscreenchanged', function (type, fullscreen) {
        if (!fullscreen) {
          var ratio = this.body.offsetWidth / document.body.offsetWidth,
            tables = domUtils.getElementsByTagName(this.body, 'table');
          utils.each(tables, function (table) {
            if (table.offsetWidth < me.body.offsetWidth) return false;
            var tds = domUtils.getElementsByTagName(table, 'td'),
              backWidths = [];
            utils.each(tds, function (td) {
              backWidths.push(td.offsetWidth);
            });
            for (var i = 0, td; (td = tds[i]); i++) {
              td.setAttribute('width', Math.floor(backWidths[i] * ratio));
            }
            table.setAttribute('width', Math.floor(getTableWidth(me, needIEHack, getDefaultValue(me))));
          });
        }
      });
      var oldExecCommand = me.execCommand;
      me.execCommand = function (cmd, datatat) {
        var me = this,
          args = arguments;
        cmd = cmd.toLowerCase();
        var ut = getUETableBySelected(me),
          tds,
          range = new dom.Range(me.document),
          cmdFun = me.commands[cmd] || UE.commands[cmd],
          result;
        if (!cmdFun) return;
        if (ut && !commands[cmd] && !cmdFun.notNeedUndo && !me.__hasEnterExecCommand) {
          me.__hasEnterExecCommand = true;
          me.fireEvent('beforeexeccommand', cmd);
          tds = ut.selectedTds;
          var lastState = -2,
            lastValue = -2,
            value,
            state;
          for (var i = 0, td; (td = tds[i]); i++) {
            if (isEmptyBlock(td)) {
              range.setStart(td, 0).setCursor(false, true);
            } else {
              range.selectNode(td).select(true);
            }
            state = me.queryCommandState(cmd);
            value = me.queryCommandValue(cmd);
            if (state != -1) {
              if (lastState !== state || lastValue !== value) {
                me._ignoreContentChange = true;
                result = oldExecCommand.apply(me, arguments);
                me._ignoreContentChange = false;
              }
              lastState = me.queryCommandState(cmd);
              lastValue = me.queryCommandValue(cmd);
              if (domUtils.isEmptyBlock(td)) {
                domUtils.fillNode(me.document, td);
              }
            }
          }
          range.setStart(tds[0], 0).shrinkBoundary(true).setCursor(false, true);
          me.fireEvent('contentchange');
          me.fireEvent('afterexeccommand', cmd);
          me.__hasEnterExecCommand = false;
          me._selectionChange();
        } else {
          result = oldExecCommand.apply(me, arguments);
        }
        return result;
      };
    });
    function removeStyleSize(obj, replaceToProperty) {
      removeStyle(obj, 'width', true);
      removeStyle(obj, 'height', true);
    }
    function removeStyle(obj, styleName, replaceToProperty) {
      if (obj.style[styleName]) {
        replaceToProperty && obj.setAttribute(styleName, parseInt(obj.style[styleName], 10));
        obj.style[styleName] = '';
      }
    }
    function getParentTdOrTh(ele) {
      if (ele.tagName == 'TD' || ele.tagName == 'TH') return ele;
      var td;
      if ((td = domUtils.findParentByTagName(ele, 'td', true) || domUtils.findParentByTagName(ele, 'th', true)))
        return td;
      return null;
    }
    function isEmptyBlock(node) {
      var reg = new RegExp(domUtils.fillChar, 'g');
      if (node[browser.ie ? 'innerText' : 'textContent'].replace(/^\s*$/, '').replace(reg, '').length > 0) {
        return 0;
      }
      for (var n in dtd.$isNotEmpty) {
        if (node.getElementsByTagName(n).length) {
          return 0;
        }
      }
      return 1;
    }
    function mouseCoords(evt) {
      if (evt.pageX || evt.pageY) {
        return { x: evt.pageX, y: evt.pageY };
      }
      return {
        x: evt.clientX + me.document.body.scrollLeft - me.document.body.clientLeft,
        y: evt.clientY + me.document.body.scrollTop - me.document.body.clientTop,
      };
    }
    function mouseMoveEvent(evt) {
      if (isEditorDisabled()) {
        return;
      }
      try {
        var target = getParentTdOrTh(evt.target || evt.srcElement),
          pos;
        if (isInResizeBuffer) {
          me.body.style.webkitUserSelect = 'none';
          if (
            Math.abs(userActionStatus.x - evt.clientX) > offsetOfTableCell ||
            Math.abs(userActionStatus.y - evt.clientY) > offsetOfTableCell
          ) {
            clearTableDragTimer();
            isInResizeBuffer = false;
            singleClickState = 0;
            tableBorderDrag(evt);
          }
        }
        if (onDrag && dragTd) {
          singleClickState = 0;
          me.body.style.webkitUserSelect = 'none';
          me.selection.getNative()[browser.ie9below ? 'empty' : 'removeAllRanges']();
          pos = mouseCoords(evt);
          toggleDraggableState(me, true, onDrag, pos, target);
          if (onDrag == 'h') {
            dragLine.style.left = getPermissionX(dragTd, evt) + 'px';
          } else if (onDrag == 'v') {
            dragLine.style.top = getPermissionY(dragTd, evt) + 'px';
          }
          return;
        }
        if (target) {
          if (me.fireEvent('excludetable', target) === true) return;
          pos = mouseCoords(evt);
          var state = getRelation(target, pos),
            table = domUtils.findParentByTagName(target, 'table', true);
          if (inTableSide(table, target, evt, true)) {
            if (me.fireEvent('excludetable', table) === true) return;
            me.body.style.cursor = 'url(' + me.options.cursorpath + 'h.png),pointer';
          } else if (inTableSide(table, target, evt)) {
            if (me.fireEvent('excludetable', table) === true) return;
            me.body.style.cursor = 'url(' + me.options.cursorpath + 'v.png),pointer';
          } else {
            me.body.style.cursor = 'text';
            var curCell = target;
            if (/\d/.test(state)) {
              state = state.replace(/\d/, '');
              target = getUETable(target).getPreviewCell(target, state == 'v');
            }
            toggleDraggableState(me, target ? !!state : false, target ? state : '', pos, target);
          }
        } else {
          toggleDragButton(false, table, me);
        }
      } catch (e) {
        showError(e);
      }
    }
    var dragButtonTimer;
    function toggleDragButton(show, table, editor) {
      if (!show) {
        if (dragOver) return;
        dragButtonTimer = setTimeout(function () {
          !dragOver && dragButton && dragButton.parentNode && dragButton.parentNode.removeChild(dragButton);
        }, 2e3);
      } else {
        createDragButton(table, editor);
      }
    }
    function createDragButton(table, editor) {
      var pos = domUtils.getXY(table),
        doc = table.ownerDocument;
      if (dragButton && dragButton.parentNode) return dragButton;
      dragButton = doc.createElement('div');
      dragButton.contentEditable = false;
      dragButton.innerHTML = '';
      dragButton.style.cssText =
        'width:15px;height:15px;background-image:url(' +
        editor.options.UEDITOR_HOME_URL +
        'dialogs/table/dragicon.png);position: absolute;cursor:move;top:' +
        (pos.y - 15) +
        'px;left:' +
        pos.x +
        'px;';
      domUtils.unSelectable(dragButton);
      dragButton.onmouseover = function (evt) {
        dragOver = true;
      };
      dragButton.onmouseout = function (evt) {
        dragOver = false;
      };
      domUtils.on(dragButton, 'click', function (type, evt) {
        doClick(evt, this);
      });
      domUtils.on(dragButton, 'dblclick', function (type, evt) {
        doDblClick(evt);
      });
      domUtils.on(dragButton, 'dragstart', function (type, evt) {
        domUtils.preventDefault(evt);
      });
      var timer;
      function doClick(evt, button) {
        clearTimeout(timer);
        timer = setTimeout(function () {
          editor.fireEvent('tableClicked', table, button);
        }, 300);
      }
      function doDblClick(evt) {
        clearTimeout(timer);
        var ut = getUETable(table),
          start = table.rows[0].cells[0],
          end = ut.getLastCell(),
          range = ut.getCellsRange(start, end);
        editor.selection.getRange().setStart(start, 0).setCursor(false, true);
        ut.setSelected(range);
      }
      doc.body.appendChild(dragButton);
    }
    function inTableSide(table, cell, evt, top) {
      var pos = mouseCoords(evt),
        state = getRelation(cell, pos);
      if (top) {
        var caption = table.getElementsByTagName('caption')[0],
          capHeight = caption ? caption.offsetHeight : 0;
        return state == 'v1' && pos.y - domUtils.getXY(table).y - capHeight < 8;
      } else {
        return state == 'h1' && pos.x - domUtils.getXY(table).x < 8;
      }
    }
    function getPermissionX(dragTd, evt) {
      var ut = getUETable(dragTd);
      if (ut) {
        var preTd = ut.getSameEndPosCells(dragTd, 'x')[0],
          nextTd = ut.getSameStartPosXCells(dragTd)[0],
          mouseX = mouseCoords(evt).x,
          left = (preTd ? domUtils.getXY(preTd).x : domUtils.getXY(ut.table).x) + 20,
          right = nextTd
            ? domUtils.getXY(nextTd).x + nextTd.offsetWidth - 20
            : me.body.offsetWidth + 5 || parseInt(domUtils.getComputedStyle(me.body, 'width'), 10);
        left += cellMinWidth;
        right -= cellMinWidth;
        return mouseX < left ? left : mouseX > right ? right : mouseX;
      }
    }
    function getPermissionY(dragTd, evt) {
      try {
        var top = domUtils.getXY(dragTd).y,
          mousePosY = mouseCoords(evt).y;
        return mousePosY < top ? top : mousePosY;
      } catch (e) {
        showError(e);
      }
    }
    function toggleDraggableState(editor, draggable, dir, mousePos, cell) {
      try {
        editor.body.style.cursor = dir == 'h' ? 'col-resize' : dir == 'v' ? 'row-resize' : 'text';
        if (browser.ie) {
          if (dir && !mousedown && !getUETableBySelected(editor)) {
            getDragLine(editor, editor.document);
            showDragLineAt(dir, cell);
          } else {
            hideDragLine(editor);
          }
        }
        onBorder = draggable;
      } catch (e) {
        showError(e);
      }
    }
    function getResizeLineByUETable() {
      var lineId = '_UETableResizeLine',
        line = this.document.getElementById(lineId);
      if (!line) {
        line = this.document.createElement('div');
        line.id = lineId;
        line.contnetEditable = false;
        line.setAttribute('unselectable', 'on');
        var styles = {
          width: 2 * cellBorderWidth + 1 + 'px',
          position: 'absolute',
          'z-index': 1e5,
          cursor: 'col-resize',
          background: 'red',
          display: 'none',
        };
        line.onmouseout = function () {
          this.style.display = 'none';
        };
        utils.extend(line.style, styles);
        this.document.body.appendChild(line);
      }
      return line;
    }
    function updateResizeLine(cell, uetable) {
      var line = getResizeLineByUETable.call(this),
        table = uetable.table,
        styles = {
          top: domUtils.getXY(table).y + 'px',
          left: domUtils.getXY(cell).x + cell.offsetWidth - cellBorderWidth + 'px',
          display: 'block',
          height: table.offsetHeight + 'px',
        };
      utils.extend(line.style, styles);
    }
    function showResizeLine(cell) {
      var uetable = getUETable(cell);
      updateResizeLine.call(this, cell, uetable);
    }
    function getRelation(ele, mousePos) {
      var elePos = domUtils.getXY(ele);
      if (!elePos) {
        return '';
      }
      if (elePos.x + ele.offsetWidth - mousePos.x < cellBorderWidth) {
        return 'h';
      }
      if (mousePos.x - elePos.x < cellBorderWidth) {
        return 'h1';
      }
      if (elePos.y + ele.offsetHeight - mousePos.y < cellBorderWidth) {
        return 'v';
      }
      if (mousePos.y - elePos.y < cellBorderWidth) {
        return 'v1';
      }
      return '';
    }
    function mouseDownEvent(type, evt) {
      if (isEditorDisabled()) {
        return;
      }
      userActionStatus = { x: evt.clientX, y: evt.clientY };
      if (evt.button == 2) {
        var ut = getUETableBySelected(me),
          flag = false;
        if (ut) {
          var td = getTargetTd(me, evt);
          utils.each(ut.selectedTds, function (ti) {
            if (ti === td) {
              flag = true;
            }
          });
          if (!flag) {
            removeSelectedClass(domUtils.getElementsByTagName(me.body, 'th td'));
            ut.clearSelected();
          } else {
            td = ut.selectedTds[0];
            setTimeout(function () {
              me.selection.getRange().setStart(td, 0).setCursor(false, true);
            }, 0);
          }
        }
      } else {
        tableClickHander(evt);
      }
    }
    function clearTableTimer() {
      tabTimer && clearTimeout(tabTimer);
      tabTimer = null;
    }
    function tableDbclickHandler(evt) {
      singleClickState = 0;
      evt = evt || me.window.event;
      var target = getParentTdOrTh(evt.target || evt.srcElement);
      if (target) {
        var h;
        if ((h = getRelation(target, mouseCoords(evt)))) {
          hideDragLine(me);
          if (h == 'h1') {
            h = 'h';
            if (inTableSide(domUtils.findParentByTagName(target, 'table'), target, evt)) {
              me.execCommand('adaptbywindow');
            } else {
              target = getUETable(target).getPreviewCell(target);
              if (target) {
                var rng = me.selection.getRange();
                rng.selectNodeContents(target).setCursor(true, true);
              }
            }
          }
          if (h == 'h') {
            var ut = getUETable(target),
              table = ut.table,
              cells = getCellsByMoveBorder(target, table, true);
            cells = extractArray(cells, 'left');
            ut.width = ut.offsetWidth;
            var oldWidth = [],
              newWidth = [];
            utils.each(cells, function (cell) {
              oldWidth.push(cell.offsetWidth);
            });
            utils.each(cells, function (cell) {
              cell.removeAttribute('width');
            });
            window.setTimeout(function () {
              var changeable = true;
              utils.each(cells, function (cell, index) {
                var width = cell.offsetWidth;
                if (width > oldWidth[index]) {
                  changeable = false;
                  return false;
                }
                newWidth.push(width);
              });
              var change = changeable ? newWidth : oldWidth;
              utils.each(cells, function (cell, index) {
                cell.width = change[index] - getTabcellSpace();
              });
            }, 0);
          }
        }
      }
    }
    function tableClickHander(evt) {
      removeSelectedClass(domUtils.getElementsByTagName(me.body, 'td th'));
      utils.each(me.document.getElementsByTagName('table'), function (t) {
        t.ueTable = null;
      });
      startTd = getTargetTd(me, evt);
      if (!startTd) return;
      var table = domUtils.findParentByTagName(startTd, 'table', true);
      ut = getUETable(table);
      ut && ut.clearSelected();
      if (!onBorder) {
        me.document.body.style.webkitUserSelect = '';
        mousedown = true;
        me.addListener('mouseover', mouseOverEvent);
      } else {
        borderActionHandler(evt);
      }
    }
    function borderActionHandler(evt) {
      if (browser.ie) {
        evt = reconstruct(evt);
      }
      clearTableDragTimer();
      isInResizeBuffer = true;
      tableDragTimer = setTimeout(function () {
        tableBorderDrag(evt);
      }, dblclickTime);
    }
    function extractArray(originArr, key) {
      var result = [],
        tmp = null;
      for (var i = 0, len = originArr.length; i < len; i++) {
        tmp = originArr[i][key];
        if (tmp) {
          result.push(tmp);
        }
      }
      return result;
    }
    function clearTableDragTimer() {
      tableDragTimer && clearTimeout(tableDragTimer);
      tableDragTimer = null;
    }
    function reconstruct(obj) {
      var attrs = ['pageX', 'pageY', 'clientX', 'clientY', 'srcElement', 'target'],
        newObj = {};
      if (obj) {
        for (var i = 0, key, val; (key = attrs[i]); i++) {
          val = obj[key];
          val && (newObj[key] = val);
        }
      }
      return newObj;
    }
    function tableBorderDrag(evt) {
      isInResizeBuffer = false;
      startTd = evt.target || evt.srcElement;
      if (!startTd) return;
      var state = getRelation(startTd, mouseCoords(evt));
      if (/\d/.test(state)) {
        state = state.replace(/\d/, '');
        startTd = getUETable(startTd).getPreviewCell(startTd, state == 'v');
      }
      hideDragLine(me);
      getDragLine(me, me.document);
      me.fireEvent('saveScene');
      showDragLineAt(state, startTd);
      mousedown = true;
      onDrag = state;
      dragTd = startTd;
    }
    function mouseUpEvent(type, evt) {
      if (isEditorDisabled()) {
        return;
      }
      clearTableDragTimer();
      isInResizeBuffer = false;
      if (onBorder) {
        singleClickState = ++singleClickState % 3;
        userActionStatus = { x: evt.clientX, y: evt.clientY };
        tableResizeTimer = setTimeout(function () {
          singleClickState > 0 && singleClickState--;
        }, dblclickTime);
        if (singleClickState === 2) {
          singleClickState = 0;
          tableDbclickHandler(evt);
          return;
        }
      }
      if (evt.button == 2) return;
      var me = this;
      var range = me.selection.getRange(),
        start = domUtils.findParentByTagName(range.startContainer, 'table', true),
        end = domUtils.findParentByTagName(range.endContainer, 'table', true);
      if (start || end) {
        if (start === end) {
          start = domUtils.findParentByTagName(range.startContainer, ['td', 'th', 'caption'], true);
          end = domUtils.findParentByTagName(range.endContainer, ['td', 'th', 'caption'], true);
          if (start !== end) {
            me.selection.clearRange();
          }
        } else {
          me.selection.clearRange();
        }
      }
      mousedown = false;
      me.document.body.style.webkitUserSelect = '';
      if (onDrag && dragTd) {
        me.selection.getNative()[browser.ie9below ? 'empty' : 'removeAllRanges']();
        singleClickState = 0;
        dragLine = me.document.getElementById('ue_tableDragLine');
        if (dragLine) {
          var dragTdPos = domUtils.getXY(dragTd),
            dragLinePos = domUtils.getXY(dragLine);
          switch (onDrag) {
            case 'h':
              changeColWidth(dragTd, dragLinePos.x - dragTdPos.x);
              break;
            case 'v':
              changeRowHeight(dragTd, dragLinePos.y - dragTdPos.y - dragTd.offsetHeight);
              break;
            default:
          }
          onDrag = '';
          dragTd = null;
          hideDragLine(me);
          me.fireEvent('saveScene');
          return;
        }
      }
      if (!startTd) {
        var target = domUtils.findParentByTagName(evt.target || evt.srcElement, 'td', true);
        if (!target) target = domUtils.findParentByTagName(evt.target || evt.srcElement, 'th', true);
        if (target && (target.tagName == 'TD' || target.tagName == 'TH')) {
          if (me.fireEvent('excludetable', target) === true) return;
          range = new dom.Range(me.document);
          range.setStart(target, 0).setCursor(false, true);
        }
      } else {
        var ut = getUETable(startTd),
          cell = ut ? ut.selectedTds[0] : null;
        if (cell) {
          range = new dom.Range(me.document);
          if (domUtils.isEmptyBlock(cell)) {
            range.setStart(cell, 0).setCursor(false, true);
          } else {
            range.selectNodeContents(cell).shrinkBoundary().setCursor(false, true);
          }
        } else {
          range = me.selection.getRange().shrinkBoundary();
          if (!range.collapsed) {
            var start = domUtils.findParentByTagName(range.startContainer, ['td', 'th'], true),
              end = domUtils.findParentByTagName(range.endContainer, ['td', 'th'], true);
            if ((start && !end) || (!start && end) || (start && end && start !== end)) {
              range.setCursor(false, true);
            }
          }
        }
        startTd = null;
        me.removeListener('mouseover', mouseOverEvent);
      }
      me._selectionChange(250, evt);
    }
    function mouseOverEvent(type, evt) {
      if (isEditorDisabled()) {
        return;
      }
      var me = this,
        tar = evt.target || evt.srcElement;
      currentTd = domUtils.findParentByTagName(tar, 'td', true) || domUtils.findParentByTagName(tar, 'th', true);
      if (
        startTd &&
        currentTd &&
        ((startTd.tagName == 'TD' && currentTd.tagName == 'TD') ||
          (startTd.tagName == 'TH' && currentTd.tagName == 'TH')) &&
        domUtils.findParentByTagName(startTd, 'table') == domUtils.findParentByTagName(currentTd, 'table')
      ) {
        var ut = getUETable(currentTd);
        if (startTd != currentTd) {
          me.document.body.style.webkitUserSelect = 'none';
          me.selection.getNative()[browser.ie9below ? 'empty' : 'removeAllRanges']();
          var range = ut.getCellsRange(startTd, currentTd);
          ut.setSelected(range);
        } else {
          me.document.body.style.webkitUserSelect = '';
          ut.clearSelected();
        }
      }
      evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);
    }
    function setCellHeight(cell, height, backHeight) {
      var lineHight = parseInt(domUtils.getComputedStyle(cell, 'line-height'), 10),
        tmpHeight = backHeight + height;
      height = tmpHeight < lineHight ? lineHight : tmpHeight;
      if (cell.style.height) cell.style.height = '';
      cell.rowSpan == 1 ? cell.setAttribute('height', height) : cell.removeAttribute && cell.removeAttribute('height');
    }
    function getWidth(cell) {
      if (!cell) return 0;
      return parseInt(domUtils.getComputedStyle(cell, 'width'), 10);
    }
    function changeColWidth(cell, changeValue) {
      var ut = getUETable(cell);
      if (ut) {
        var table = ut.table,
          cells = getCellsByMoveBorder(cell, table);
        table.style.width = '';
        table.removeAttribute('width');
        changeValue = correctChangeValue(changeValue, cell, cells);
        if (cell.nextSibling) {
          var i = 0;
          utils.each(cells, function (cellGroup) {
            cellGroup.left.width = +cellGroup.left.width + changeValue;
            cellGroup.right && (cellGroup.right.width = +cellGroup.right.width - changeValue);
          });
        } else {
          utils.each(cells, function (cellGroup) {
            cellGroup.left.width -= -changeValue;
          });
        }
      }
    }
    function isEditorDisabled() {
      return me.body.contentEditable === 'false';
    }
    function changeRowHeight(td, changeValue) {
      if (Math.abs(changeValue) < 10) return;
      var ut = getUETable(td);
      if (ut) {
        var cells = ut.getSameEndPosCells(td, 'y'),
          backHeight = cells[0] ? cells[0].offsetHeight : 0;
        for (var i = 0, cell; (cell = cells[i++]); ) {
          setCellHeight(cell, changeValue, backHeight);
        }
      }
    }
    function getCellsByMoveBorder(cell, table, isContainMergeCell) {
      if (!table) {
        table = domUtils.findParentByTagName(cell, 'table');
      }
      if (!table) {
        return null;
      }
      var index = domUtils.getNodeIndex(cell),
        temp = cell,
        rows = table.rows,
        colIndex = 0;
      while (temp) {
        if (temp.nodeType === 1) {
          colIndex += temp.colSpan || 1;
        }
        temp = temp.previousSibling;
      }
      temp = null;
      var borderCells = [];
      utils.each(rows, function (tabRow) {
        var cells = tabRow.cells,
          currIndex = 0;
        utils.each(cells, function (tabCell) {
          currIndex += tabCell.colSpan || 1;
          if (currIndex === colIndex) {
            borderCells.push({ left: tabCell, right: tabCell.nextSibling || null });
            return false;
          } else if (currIndex > colIndex) {
            if (isContainMergeCell) {
              borderCells.push({ left: tabCell });
            }
            return false;
          }
        });
      });
      return borderCells;
    }
    function getMinWidthByTableCells(cells) {
      var minWidth = Number.MAX_VALUE;
      for (var i = 0, curCell; (curCell = cells[i]); i++) {
        minWidth = Math.min(minWidth, curCell.width || getTableCellWidth(curCell));
      }
      return minWidth;
    }
    function correctChangeValue(changeValue, relatedCell, cells) {
      changeValue -= getTabcellSpace();
      if (changeValue < 0) {
        return 0;
      }
      changeValue -= getTableCellWidth(relatedCell);
      var direction = changeValue < 0 ? 'left' : 'right';
      changeValue = Math.abs(changeValue);
      utils.each(cells, function (cellGroup) {
        var curCell = cellGroup[direction];
        if (curCell) {
          changeValue = Math.min(changeValue, getTableCellWidth(curCell) - cellMinWidth);
        }
      });
      changeValue = changeValue < 0 ? 0 : changeValue;
      return direction === 'left' ? -changeValue : changeValue;
    }
    function getTableCellWidth(cell) {
      var width = 0,
        offset = 0,
        width = cell.offsetWidth - getTabcellSpace();
      if (!cell.nextSibling) {
        width -= getTableCellOffset(cell);
      }
      width = width < 0 ? 0 : width;
      try {
        cell.width = width;
      } catch (e) {}
      return width;
    }
    function getTableCellOffset(cell) {
      tab = domUtils.findParentByTagName(cell, 'table', false);
      if (tab.offsetVal === undefined) {
        var prev = cell.previousSibling;
        if (prev) {
          tab.offsetVal = cell.offsetWidth - prev.offsetWidth === UT.borderWidth ? UT.borderWidth : 0;
        } else {
          tab.offsetVal = 0;
        }
      }
      return tab.offsetVal;
    }
    function getTabcellSpace() {
      if (UT.tabcellSpace === undefined) {
        var cell = null,
          tab = me.document.createElement('table'),
          tbody = me.document.createElement('tbody'),
          trow = me.document.createElement('tr'),
          tabcell = me.document.createElement('td'),
          mirror = null;
        tabcell.style.cssText = 'border: 0;';
        tabcell.width = 1;
        trow.appendChild(tabcell);
        trow.appendChild((mirror = tabcell.cloneNode(false)));
        tbody.appendChild(trow);
        tab.appendChild(tbody);
        tab.style.cssText = 'visibility: hidden;';
        me.body.appendChild(tab);
        UT.paddingSpace = tabcell.offsetWidth - 1;
        var tmpTabWidth = tab.offsetWidth;
        tabcell.style.cssText = '';
        mirror.style.cssText = '';
        UT.borderWidth = (tab.offsetWidth - tmpTabWidth) / 3;
        UT.tabcellSpace = UT.paddingSpace + UT.borderWidth;
        me.body.removeChild(tab);
      }
      getTabcellSpace = function () {
        return UT.tabcellSpace;
      };
      return UT.tabcellSpace;
    }
    function getDragLine(editor, doc) {
      if (mousedown) return;
      dragLine = editor.document.createElement('div');
      domUtils.setAttributes(dragLine, {
        id: 'ue_tableDragLine',
        unselectable: 'on',
        contenteditable: false,
        onresizestart: 'return false',
        ondragstart: 'return false',
        onselectstart: 'return false',
        style:
          'background-color:blue;position:absolute;padding:0;margin:0;background-image:none;border:0px none;opacity:0;filter:alpha(opacity=0)',
      });
      editor.body.appendChild(dragLine);
    }
    function hideDragLine(editor) {
      if (mousedown) return;
      var line;
      while ((line = editor.document.getElementById('ue_tableDragLine'))) {
        domUtils.remove(line);
      }
    }
    function showDragLineAt(state, cell) {
      if (!cell) return;
      var table = domUtils.findParentByTagName(cell, 'table'),
        caption = table.getElementsByTagName('caption'),
        width = table.offsetWidth,
        height = table.offsetHeight - (caption.length > 0 ? caption[0].offsetHeight : 0),
        tablePos = domUtils.getXY(table),
        cellPos = domUtils.getXY(cell),
        css;
      switch (state) {
        case 'h':
          css =
            'height:' +
            height +
            'px;top:' +
            (tablePos.y + (caption.length > 0 ? caption[0].offsetHeight : 0)) +
            'px;left:' +
            (cellPos.x + cell.offsetWidth);
          dragLine.style.cssText =
            css +
            'px;position: absolute;display:block;background-color:blue;width:1px;border:0; color:blue;opacity:.3;filter:alpha(opacity=30)';
          break;
        case 'v':
          css = 'width:' + width + 'px;left:' + tablePos.x + 'px;top:' + (cellPos.y + cell.offsetHeight);
          dragLine.style.cssText =
            css +
            'px;overflow:hidden;position: absolute;display:block;background-color:blue;height:1px;border:0;color:blue;opacity:.2;filter:alpha(opacity=20)';
          break;
        default:
      }
    }
    function switchBorderColor(editor, flag) {
      var tableArr = domUtils.getElementsByTagName(editor.body, 'table'),
        color;
      for (var i = 0, node; (node = tableArr[i++]); ) {
        var td = domUtils.getElementsByTagName(node, 'td');
        if (td[0]) {
          if (flag) {
            color = td[0].style.borderColor.replace(/\s/g, '');
            if (/(#ffffff)|(rgb\(255,255,255\))/gi.test(color)) domUtils.addClass(node, 'noBorderTable');
          } else {
            domUtils.removeClasses(node, 'noBorderTable');
          }
        }
      }
    }
    function getTableWidth(editor, needIEHack, defaultValue) {
      var body = editor.body;
      return (
        body.offsetWidth -
        (needIEHack ? parseInt(domUtils.getComputedStyle(body, 'margin-left'), 10) * 2 : 0) -
        defaultValue.tableBorder * 2 -
        (editor.options.offsetWidth || 0)
      );
    }
    function getTargetTd(editor, evt) {
      var target = domUtils.findParentByTagName(evt.target || evt.srcElement, ['td', 'th'], true),
        dir = null;
      if (!target) {
        return null;
      }
      dir = getRelation(target, mouseCoords(evt));
      if (!target) {
        return null;
      }
      if (dir === 'h1' && target.previousSibling) {
        var position = domUtils.getXY(target),
          cellWidth = target.offsetWidth;
        if (Math.abs(position.x + cellWidth - evt.clientX) > cellWidth / 3) {
          target = target.previousSibling;
        }
      } else if (dir === 'v1' && target.parentNode.previousSibling) {
        var position = domUtils.getXY(target),
          cellHeight = target.offsetHeight;
        if (Math.abs(position.y + cellHeight - evt.clientY) > cellHeight / 3) {
          target = target.parentNode.previousSibling.firstChild;
        }
      }
      return target && !(editor.fireEvent('excludetable', target) === true) ? target : null;
    }
  };
  UE.UETable.prototype.sortTable = function (sortByCellIndex, compareFn) {
    var table = this.table,
      rows = table.rows,
      trArray = [],
      flag = rows[0].cells[0].tagName === 'TH',
      lastRowIndex = 0;
    if (this.selectedTds.length) {
      var range = this.cellsRange,
        len = range.endRowIndex + 1;
      for (var i = range.beginRowIndex; i < len; i++) {
        trArray[i] = rows[i];
      }
      trArray.splice(0, range.beginRowIndex);
      lastRowIndex = range.endRowIndex + 1 === this.rowsNum ? 0 : range.endRowIndex + 1;
    } else {
      for (var i = 0, len = rows.length; i < len; i++) {
        trArray[i] = rows[i];
      }
    }
    var Fn = {
      reversecurrent: function (td1, td2) {
        return 1;
      },
      orderbyasc: function (td1, td2) {
        var value1 = td1.innerText || td1.textContent,
          value2 = td2.innerText || td2.textContent;
        return value1.localeCompare(value2);
      },
      reversebyasc: function (td1, td2) {
        var value1 = td1.innerHTML,
          value2 = td2.innerHTML;
        return value2.localeCompare(value1);
      },
      orderbynum: function (td1, td2) {
        var value1 = td1[browser.ie ? 'innerText' : 'textContent'].match(/\d+/),
          value2 = td2[browser.ie ? 'innerText' : 'textContent'].match(/\d+/);
        if (value1) value1 = +value1[0];
        if (value2) value2 = +value2[0];
        return (value1 || 0) - (value2 || 0);
      },
      reversebynum: function (td1, td2) {
        var value1 = td1[browser.ie ? 'innerText' : 'textContent'].match(/\d+/),
          value2 = td2[browser.ie ? 'innerText' : 'textContent'].match(/\d+/);
        if (value1) value1 = +value1[0];
        if (value2) value2 = +value2[0];
        return (value2 || 0) - (value1 || 0);
      },
    };
    table.setAttribute('data-sort-type', compareFn && typeof compareFn === 'string' && Fn[compareFn] ? compareFn : '');
    flag && trArray.splice(0, 1);
    trArray = utils.sort(trArray, function (tr1, tr2) {
      var result;
      if (compareFn && typeof compareFn === 'function') {
        result = compareFn.call(this, tr1.cells[sortByCellIndex], tr2.cells[sortByCellIndex]);
      } else if (compareFn && typeof compareFn === 'number') {
        result = 1;
      } else if (compareFn && typeof compareFn === 'string' && Fn[compareFn]) {
        result = Fn[compareFn].call(this, tr1.cells[sortByCellIndex], tr2.cells[sortByCellIndex]);
      } else {
        result = Fn['orderbyasc'].call(this, tr1.cells[sortByCellIndex], tr2.cells[sortByCellIndex]);
      }
      return result;
    });
    var fragment = table.ownerDocument.createDocumentFragment();
    for (var j = 0, len = trArray.length; j < len; j++) {
      fragment.appendChild(trArray[j]);
    }
    var tbody = table.getElementsByTagName('tbody')[0];
    if (!lastRowIndex) {
      tbody.appendChild(fragment);
    } else {
      tbody.insertBefore(fragment, rows[lastRowIndex - range.endRowIndex + range.beginRowIndex - 1]);
    }
  };
  UE.plugins['tablesort'] = function () {
    var me = this,
      UT = UE.UETable,
      getUETable = function (tdOrTable) {
        return UT.getUETable(tdOrTable);
      },
      getTableItemsByRange = function (editor) {
        return UT.getTableItemsByRange(editor);
      };
    me.ready(function () {
      utils.cssRule(
        'tablesort',
        'table.sortEnabled tr.firstRow th,table.sortEnabled tr.firstRow td{padding-right:20px;background-repeat: no-repeat;background-position: center right;' +
          '   background-image:url(' +
          me.options.themePath +
          me.options.theme +
          '/images/sortable.png);}',
        me.document,
      );
      me.addListener('afterexeccommand', function (type, cmd) {
        if (cmd == 'mergeright' || cmd == 'mergedown' || cmd == 'mergecells') {
          this.execCommand('disablesort');
        }
      });
    });
    UE.commands['sorttable'] = {
      queryCommandState: function () {
        var me = this,
          tableItems = getTableItemsByRange(me);
        if (!tableItems.cell) return -1;
        var table = tableItems.table,
          cells = table.getElementsByTagName('td');
        for (var i = 0, cell; (cell = cells[i++]); ) {
          if (cell.rowSpan != 1 || cell.colSpan != 1) return -1;
        }
        return 0;
      },
      execCommand: function (cmd, fn) {
        var me = this,
          range = me.selection.getRange(),
          bk = range.createBookmark(true),
          tableItems = getTableItemsByRange(me),
          cell = tableItems.cell,
          ut = getUETable(tableItems.table),
          cellInfo = ut.getCellInfo(cell);
        ut.sortTable(cellInfo.cellIndex, fn);
        range.moveToBookmark(bk);
        try {
          range.select();
        } catch (e) {}
      },
    };
    UE.commands['enablesort'] = UE.commands['disablesort'] = {
      queryCommandState: function (cmd) {
        var table = getTableItemsByRange(this).table;
        if (table && cmd == 'enablesort') {
          var cells = domUtils.getElementsByTagName(table, 'th td');
          for (var i = 0; i < cells.length; i++) {
            if (cells[i].getAttribute('colspan') > 1 || cells[i].getAttribute('rowspan') > 1) return -1;
          }
        }
        return !table ? -1 : (cmd == 'enablesort') ^ (table.getAttribute('data-sort') != 'sortEnabled') ? -1 : 0;
      },
      execCommand: function (cmd) {
        var table = getTableItemsByRange(this).table;
        table.setAttribute('data-sort', cmd == 'enablesort' ? 'sortEnabled' : 'sortDisabled');
        cmd == 'enablesort' ? domUtils.addClass(table, 'sortEnabled') : domUtils.removeClasses(table, 'sortEnabled');
      },
    };
  };
  UE.plugins['contextmenu'] = function () {
    var me = this;
    me.setOpt('enableContextMenu', me.getOpt('enableContextMenu') || true);
    if (me.getOpt('enableContextMenu') === false) {
      return;
    }
    var lang = me.getLang('contextMenu'),
      menu,
      items = me.options.contextMenu || [
        { label: lang['selectall'], cmdName: 'selectall' },
        {
          label: lang.cleardoc,
          cmdName: 'cleardoc',
          exec: function () {
            if (confirm(lang.confirmclear)) {
              this.execCommand('cleardoc');
            }
          },
        },
        '-',
        { label: lang.unlink, cmdName: 'unlink' },
        '-',
        {
          group: lang.paragraph,
          icon: 'justifyjustify',
          subMenu: [
            { label: lang.justifyleft, cmdName: 'justify', value: 'left' },
            { label: lang.justifyright, cmdName: 'justify', value: 'right' },
            { label: lang.justifycenter, cmdName: 'justify', value: 'center' },
            { label: lang.justifyjustify, cmdName: 'justify', value: 'justify' },
          ],
        },
        '-',
        {
          group: lang.table,
          icon: 'table',
          subMenu: [
            { label: lang.inserttable, cmdName: 'inserttable' },
            { label: lang.deletetable, cmdName: 'deletetable' },
            '-',
            { label: lang.deleterow, cmdName: 'deleterow' },
            { label: lang.deletecol, cmdName: 'deletecol' },
            { label: lang.insertcol, cmdName: 'insertcol' },
            { label: lang.insertcolnext, cmdName: 'insertcolnext' },
            { label: lang.insertrow, cmdName: 'insertrow' },
            { label: lang.insertrownext, cmdName: 'insertrownext' },
            '-',
            { label: lang.insertcaption, cmdName: 'insertcaption' },
            { label: lang.deletecaption, cmdName: 'deletecaption' },
            { label: lang.inserttitle, cmdName: 'inserttitle' },
            { label: lang.deletetitle, cmdName: 'deletetitle' },
            { label: lang.inserttitlecol, cmdName: 'inserttitlecol' },
            { label: lang.deletetitlecol, cmdName: 'deletetitlecol' },
            '-',
            { label: lang.mergecells, cmdName: 'mergecells' },
            { label: lang.mergeright, cmdName: 'mergeright' },
            { label: lang.mergedown, cmdName: 'mergedown' },
            '-',
            { label: lang.splittorows, cmdName: 'splittorows' },
            { label: lang.splittocols, cmdName: 'splittocols' },
            { label: lang.splittocells, cmdName: 'splittocells' },
            '-',
            { label: lang.averageDiseRow, cmdName: 'averagedistributerow' },
            { label: lang.averageDisCol, cmdName: 'averagedistributecol' },
            '-',
            {
              label: lang.edittd,
              cmdName: 'edittd',
              exec: function () {
                if (UE.ui['edittd']) {
                  new UE.ui['edittd'](this);
                }
                this.getDialog('edittd').open();
              },
            },
            {
              label: lang.edittable,
              cmdName: 'edittable',
              exec: function () {
                if (UE.ui['edittable']) {
                  new UE.ui['edittable'](this);
                }
                this.getDialog('edittable').open();
              },
            },
            { label: lang.setbordervisible, cmdName: 'setbordervisible' },
          ],
        },
        {
          group: lang.tablesort,
          icon: 'tablesort',
          subMenu: [
            { label: lang.enablesort, cmdName: 'enablesort' },
            { label: lang.disablesort, cmdName: 'disablesort' },
            '-',
            { label: lang.reversecurrent, cmdName: 'sorttable', value: 'reversecurrent' },
            { label: lang.orderbyasc, cmdName: 'sorttable', value: 'orderbyasc' },
            { label: lang.reversebyasc, cmdName: 'sorttable', value: 'reversebyasc' },
            { label: lang.orderbynum, cmdName: 'sorttable', value: 'orderbynum' },
            { label: lang.reversebynum, cmdName: 'sorttable', value: 'reversebynum' },
          ],
        },
        {
          group: lang.borderbk,
          icon: 'borderBack',
          subMenu: [
            {
              label: lang.setcolor,
              cmdName: 'interlacetable',
              exec: function () {
                this.execCommand('interlacetable');
              },
            },
            {
              label: lang.unsetcolor,
              cmdName: 'uninterlacetable',
              exec: function () {
                this.execCommand('uninterlacetable');
              },
            },
            {
              label: lang.setbackground,
              cmdName: 'settablebackground',
              exec: function () {
                this.execCommand('settablebackground', { repeat: true, colorList: ['#bbb', '#ccc'] });
              },
            },
            {
              label: lang.unsetbackground,
              cmdName: 'cleartablebackground',
              exec: function () {
                this.execCommand('cleartablebackground');
              },
            },
            {
              label: lang.redandblue,
              cmdName: 'settablebackground',
              exec: function () {
                this.execCommand('settablebackground', { repeat: true, colorList: ['red', 'blue'] });
              },
            },
            {
              label: lang.threecolorgradient,
              cmdName: 'settablebackground',
              exec: function () {
                this.execCommand('settablebackground', { repeat: true, colorList: ['#aaa', '#bbb', '#ccc'] });
              },
            },
          ],
        },
        {
          group: lang.aligntd,
          icon: 'aligntd',
          subMenu: [
            { cmdName: 'cellalignment', value: { align: 'left', vAlign: 'top' } },
            { cmdName: 'cellalignment', value: { align: 'center', vAlign: 'top' } },
            { cmdName: 'cellalignment', value: { align: 'right', vAlign: 'top' } },
            { cmdName: 'cellalignment', value: { align: 'left', vAlign: 'middle' } },
            { cmdName: 'cellalignment', value: { align: 'center', vAlign: 'middle' } },
            { cmdName: 'cellalignment', value: { align: 'right', vAlign: 'middle' } },
            { cmdName: 'cellalignment', value: { align: 'left', vAlign: 'bottom' } },
            { cmdName: 'cellalignment', value: { align: 'center', vAlign: 'bottom' } },
            { cmdName: 'cellalignment', value: { align: 'right', vAlign: 'bottom' } },
          ],
        },
        {
          group: lang.aligntable,
          icon: 'aligntable',
          subMenu: [
            { cmdName: 'tablealignment', className: 'left', label: lang.tableleft, value: 'left' },
            { cmdName: 'tablealignment', className: 'center', label: lang.tablecenter, value: 'center' },
            { cmdName: 'tablealignment', className: 'right', label: lang.tableright, value: 'right' },
          ],
        },
        '-',
        { label: lang.insertparagraphbefore, cmdName: 'insertparagraph', value: true },
        { label: lang.insertparagraphafter, cmdName: 'insertparagraph' },
        { label: lang['copy'], cmdName: 'copy' },
        { label: lang['paste'], cmdName: 'paste' },
      ];
    if (!items.length) {
      return;
    }
    var uiUtils = UE.ui.uiUtils;
    me.addListener('contextmenu', function (type, evt) {
      var offset = uiUtils.getViewportOffsetByEvent(evt);
      me.fireEvent('beforeselectionchange');
      if (menu) {
        menu.destroy();
      }
      for (var i = 0, ti, contextItems = []; (ti = items[i]); i++) {
        var last;
        (function (item) {
          if (item == '-') {
            if ((last = contextItems[contextItems.length - 1]) && last !== '-') {
              contextItems.push('-');
            }
          } else if (item.hasOwnProperty('group')) {
            for (var j = 0, cj, subMenu = []; (cj = item.subMenu[j]); j++) {
              (function (subItem) {
                if (subItem == '-') {
                  if ((last = subMenu[subMenu.length - 1]) && last !== '-') {
                    subMenu.push('-');
                  } else {
                    subMenu.splice(subMenu.length - 1);
                  }
                } else {
                  if (
                    (me.commands[subItem.cmdName] || UE.commands[subItem.cmdName] || subItem.query) &&
                    (subItem.query ? subItem.query() : me.queryCommandState(subItem.cmdName)) > -1
                  ) {
                    subMenu.push({
                      label:
                        subItem.label || me.getLang('contextMenu.' + subItem.cmdName + (subItem.value || '')) || '',
                      className:
                        'edui-for-' +
                        subItem.cmdName +
                        (subItem.className ? ' edui-for-' + subItem.cmdName + '-' + subItem.className : ''),
                      onclick: subItem.exec
                        ? function () {
                            subItem.exec.call(me);
                          }
                        : function () {
                            me.execCommand(subItem.cmdName, subItem.value);
                          },
                    });
                  }
                }
              })(cj);
            }
            if (subMenu.length) {
              function getLabel() {
                switch (item.icon) {
                  case 'table':
                    return me.getLang('contextMenu.table');
                  case 'justifyjustify':
                    return me.getLang('contextMenu.paragraph');
                  case 'aligntd':
                    return me.getLang('contextMenu.aligntd');
                  case 'aligntable':
                    return me.getLang('contextMenu.aligntable');
                  case 'tablesort':
                    return lang.tablesort;
                  case 'borderBack':
                    return lang.borderbk;
                  default:
                    return '';
                }
              }
              contextItems.push({
                label: getLabel(),
                className: 'edui-for-' + item.icon,
                subMenu: { items: subMenu, editor: me },
              });
            }
          } else {
            if (
              (me.commands[item.cmdName] || UE.commands[item.cmdName] || item.query) &&
              (item.query ? item.query.call(me) : me.queryCommandState(item.cmdName)) > -1
            ) {
              contextItems.push({
                label: item.label || me.getLang('contextMenu.' + item.cmdName),
                className: 'edui-for-' + (item.icon ? item.icon : item.cmdName + (item.value || '')),
                onclick: item.exec
                  ? function () {
                      item.exec.call(me);
                    }
                  : function () {
                      me.execCommand(item.cmdName, item.value);
                    },
              });
            }
          }
        })(ti);
      }
      if (contextItems[contextItems.length - 1] == '-') {
        contextItems.pop();
      }
      menu = new UE.ui.Menu({ items: contextItems, className: 'edui-contextmenu', editor: me });
      menu.render();
      menu.showAt(offset);
      me.fireEvent('aftershowcontextmenu', menu);
      domUtils.preventDefault(evt);
      if (browser.ie) {
        var ieRange;
        try {
          ieRange = me.selection.getNative().createRange();
        } catch (e) {
          return;
        }
        if (ieRange.item) {
          var range = new dom.Range(me.document);
          range.selectNode(ieRange.item(0)).select(true, true);
        }
      }
    });
    me.addListener('aftershowcontextmenu', function (type, menu) {
      if (me.zeroclipboard) {
        var items = menu.items;
        for (var key in items) {
          if (items[key].className == 'edui-for-copy') {
            me.zeroclipboard.clip(items[key].getDom());
          }
        }
      }
    });
  };
  UE.plugins['shortcutmenu'] = function () {
    var me = this,
      menu,
      items = me.options.shortcutMenu || [];
    if (!items.length) {
      return;
    }
    me.addListener('mouseup', function (type, e) {
      var me = this,
        customEvt = {
          type: type,
          target: e.target || e.srcElement,
          screenX: e.screenX,
          screenY: e.screenY,
          clientX: e.clientX,
          clientY: e.clientY,
        };
      setTimeout(function () {
        if (!menu) {
          menu = new baidu.editor.ui.ShortCutMenu({
            editor: me,
            items: items.concat([]),
            theme: me.options.theme,
            className: 'edui-shortcutmenu',
          });
          menu.render();
          me.fireEvent('afterrendershortcutmenu', menu);
        }
        menu.show(customEvt, !!UE.plugins['contextmenu']);
      });
      if (type === 'contextmenu') {
        domUtils.preventDefault(e);
        if (browser.ie9below) {
          var ieRange;
          try {
            ieRange = me.selection.getNative().createRange();
          } catch (e) {
            return;
          }
          if (ieRange.item) {
            var range = new dom.Range(me.document);
            range.selectNode(ieRange.item(0)).select(true, true);
          }
        }
      }
    });
    me.addListener('keydown', function (type) {
      if (type === 'keydown') {
        menu && !menu.isHidden && menu.hide();
      }
    });
  };
  UE.plugins['basestyle'] = function () {
    var basestyles = { bold: ['strong', 'b'], italic: ['em', 'i'], subscript: ['sub'], superscript: ['sup'] },
      getObj = function (editor, tagNames) {
        return domUtils.filterNodeList(editor.selection.getStartElementPath(), tagNames);
      },
      me = this;
    me.addshortcutkey({ Bold: 'ctrl+66', Italic: 'ctrl+73', Underline: 'ctrl+85' });
    me.addInputRule(function (root) {
      utils.each(root.getNodesByTagName('b i'), function (node) {
        switch (node.tagName) {
          case 'b':
            node.tagName = 'strong';
            break;
          case 'i':
            node.tagName = 'em';
        }
      });
    });
    for (var style in basestyles) {
      (function (cmd, tagNames) {
        me.commands[cmd] = {
          execCommand: function (cmdName) {
            var range = me.selection.getRange(),
              obj = getObj(this, tagNames);
            if (range.collapsed) {
              if (obj) {
                var tmpText = me.document.createTextNode('');
                range.insertNode(tmpText).removeInlineStyle(tagNames);
                range.setStartBefore(tmpText);
                domUtils.remove(tmpText);
              } else {
                var tmpNode = range.document.createElement(tagNames[0]);
                if (cmdName == 'superscript' || cmdName == 'subscript') {
                  tmpText = me.document.createTextNode('');
                  range.insertNode(tmpText).removeInlineStyle(['sub', 'sup']).setStartBefore(tmpText).collapse(true);
                }
                range.insertNode(tmpNode).setStart(tmpNode, 0);
              }
              range.collapse(true);
            } else {
              if (cmdName == 'superscript' || cmdName == 'subscript') {
                if (!obj || obj.tagName.toLowerCase() != cmdName) {
                  range.removeInlineStyle(['sub', 'sup']);
                }
              }
              obj ? range.removeInlineStyle(tagNames) : range.applyInlineStyle(tagNames[0]);
            }
            range.select();
          },
          queryCommandState: function () {
            return getObj(this, tagNames) ? 1 : 0;
          },
        };
      })(style, basestyles[style]);
    }
  };
  UE.plugins['elementpath'] = function () {
    var currentLevel,
      tagNames,
      me = this;
    me.setOpt('elementPathEnabled', true);
    if (!me.options.elementPathEnabled) {
      return;
    }
    me.commands['elementpath'] = {
      execCommand: function (cmdName, level) {
        var start = tagNames[level],
          range = me.selection.getRange();
        currentLevel = level * 1;
        range.selectNode(start).select();
      },
      queryCommandValue: function () {
        var parents = [].concat(this.selection.getStartElementPath()).reverse(),
          names = [];
        tagNames = parents;
        for (var i = 0, ci; (ci = parents[i]); i++) {
          if (ci.nodeType == 3) {
            continue;
          }
          var name = ci.tagName.toLowerCase();
          if (name == 'img' && ci.getAttribute('anchorname')) {
            name = 'anchor';
          }
          names[i] = name;
          if (currentLevel == i) {
            currentLevel = -1;
            break;
          }
        }
        return names;
      },
    };
  };
  UE.plugins['formatmatch'] = function () {
    var me = this,
      list = [],
      img,
      flag = 0;
    me.addListener('reset', function () {
      list = [];
      flag = 0;
    });
    function addList(type, evt) {
      if (browser.webkit) {
        var target = evt.target.tagName == 'IMG' ? evt.target : null;
      }
      function addFormat(range) {
        if (text) {
          range.selectNode(text);
        }
        return range.applyInlineStyle(list[list.length - 1].tagName, null, list);
      }
      me.undoManger && me.undoManger.save();
      var range = me.selection.getRange(),
        imgT = target || range.getClosedNode();
      if (img && imgT && imgT.tagName == 'IMG') {
        imgT.style.cssText +=
          ';float:' +
          (img.style.cssFloat || img.style.styleFloat || 'none') +
          ';display:' +
          (img.style.display || 'inline');
        img = null;
      } else {
        if (!img) {
          var collapsed = range.collapsed;
          if (collapsed) {
            var text = me.document.createTextNode('match');
            range.insertNode(text).select();
          }
          me.__hasEnterExecCommand = true;
          var removeFormatAttributes = me.options.removeFormatAttributes;
          me.options.removeFormatAttributes = '';
          me.execCommand('removeformat');
          me.options.removeFormatAttributes = removeFormatAttributes;
          me.__hasEnterExecCommand = false;
          range = me.selection.getRange();
          if (list.length) {
            addFormat(range);
          }
          if (text) {
            range.setStartBefore(text).collapse(true);
          }
          range.select();
          text && domUtils.remove(text);
        }
      }
      me.undoManger && me.undoManger.save();
    }
    me.commands['formatmatch'] = {
      execCommand: function (cmdName) {
        if (flag) {
          flag = 0;
          list = [];
          me.removeListener('mouseup', addList);
          return;
        }
        var range = me.selection.getRange();
        img = range.getClosedNode();
        if (!img || img.tagName != 'IMG') {
          range.collapse(true).shrinkBoundary();
          var start = range.startContainer;
          list = domUtils.findParents(start, true, function (node) {
            return !domUtils.isBlockElm(node) && node.nodeType == 1;
          });
          for (var i = 0, ci; (ci = list[i]); i++) {
            if (ci.tagName == 'A') {
              list.splice(i, 1);
              break;
            }
          }
        }
        me.addListener('mouseup', addList);
        flag = 1;
      },
      queryCommandState: function () {
        return flag;
      },
      notNeedUndo: 1,
    };
  };
  UE.plugin.register('searchreplace', function () {
    var me = this;
    var _blockElm = { table: 1, tbody: 1, tr: 1, ol: 1, ul: 1 };
    var lastRng = null;
    function getText(node) {
      var text = node.nodeType == 3 ? node.nodeValue : node[browser.ie ? 'innerText' : 'textContent'];
      return text.replace(domUtils.fillChar, '');
    }
    function findTextInString(textContent, opt, currentIndex) {
      var str = opt.searchStr;
      var reg = new RegExp(str, 'g' + (opt.casesensitive ? '' : 'i')),
        match;
      if (opt.dir == -1) {
        textContent = textContent.substr(0, currentIndex);
        textContent = textContent.split('').reverse().join('');
        str = str.split('').reverse().join('');
        match = reg.exec(textContent);
        if (match) {
          return currentIndex - match.index - str.length;
        }
      } else {
        textContent = textContent.substr(currentIndex);
        match = reg.exec(textContent);
        if (match) {
          return match.index + currentIndex;
        }
      }
      return -1;
    }
    function findTextBlockElm(node, currentIndex, opt) {
      var textContent,
        index,
        methodName = opt.all || opt.dir == 1 ? 'getNextDomNode' : 'getPreDomNode';
      if (domUtils.isBody(node)) {
        node = node.firstChild;
      }
      var first = 1;
      while (node) {
        textContent = getText(node);
        index = findTextInString(textContent, opt, currentIndex);
        first = 0;
        if (index != -1) {
          return { node: node, index: index };
        }
        node = domUtils[methodName](node);
        while (node && _blockElm[node.nodeName.toLowerCase()]) {
          node = domUtils[methodName](node, true);
        }
        if (node) {
          currentIndex = opt.dir == -1 ? getText(node).length : 0;
        }
      }
    }
    function findNTextInBlockElm(node, index, str) {
      var currentIndex = 0,
        currentNode = node.firstChild,
        currentNodeLength = 0,
        result;
      while (currentNode) {
        if (currentNode.nodeType == 3) {
          currentNodeLength = getText(currentNode).replace(/(^[\t\r\n]+)|([\t\r\n]+$)/, '').length;
          currentIndex += currentNodeLength;
          if (currentIndex >= index) {
            return { node: currentNode, index: currentNodeLength - (currentIndex - index) };
          }
        } else if (!dtd.$empty[currentNode.tagName]) {
          currentNodeLength = getText(currentNode).replace(/(^[\t\r\n]+)|([\t\r\n]+$)/, '').length;
          currentIndex += currentNodeLength;
          if (currentIndex >= index) {
            result = findNTextInBlockElm(currentNode, currentNodeLength - (currentIndex - index), str);
            if (result) {
              return result;
            }
          }
        }
        currentNode = domUtils.getNextDomNode(currentNode);
      }
    }
    function searchReplace(me, opt) {
      var rng = lastRng || me.selection.getRange(),
        startBlockNode,
        searchStr = opt.searchStr,
        span = me.document.createElement('span');
      span.innerHTML = '$$ueditor_searchreplace_key$$';
      rng.shrinkBoundary(true);
      if (!rng.collapsed) {
        rng.select();
        var rngText = me.selection.getText();
        if (new RegExp('^' + opt.searchStr + '$', opt.casesensitive ? '' : 'i').test(rngText)) {
          if (opt.replaceStr != undefined) {
            replaceText(rng, opt.replaceStr);
            rng.select();
            return true;
          } else {
            rng.collapse(opt.dir == -1);
          }
        }
      }
      rng.insertNode(span);
      rng.enlargeToBlockElm(true);
      startBlockNode = rng.startContainer;
      var currentIndex = getText(startBlockNode).indexOf('$$ueditor_searchreplace_key$$');
      rng.setStartBefore(span);
      domUtils.remove(span);
      var result = findTextBlockElm(startBlockNode, currentIndex, opt);
      if (result) {
        var rngStart = findNTextInBlockElm(result.node, result.index, searchStr);
        var rngEnd = findNTextInBlockElm(result.node, result.index + searchStr.length, searchStr);
        rng.setStart(rngStart.node, rngStart.index).setEnd(rngEnd.node, rngEnd.index);
        if (opt.replaceStr !== undefined) {
          replaceText(rng, opt.replaceStr);
        }
        rng.select();
        return true;
      } else {
        rng.setCursor();
      }
    }
    function replaceText(rng, str) {
      str = me.document.createTextNode(str);
      rng.deleteContents().insertNode(str);
    }
    return {
      commands: {
        searchreplace: {
          execCommand: function (cmdName, opt) {
            utils.extend(opt, { all: false, casesensitive: false, dir: 1 }, true);
            var num = 0;
            if (opt.all) {
              lastRng = null;
              var rng = me.selection.getRange(),
                first = me.body.firstChild;
              if (first && first.nodeType == 1) {
                rng.setStart(first, 0);
                rng.shrinkBoundary(true);
              } else if (first.nodeType == 3) {
                rng.setStartBefore(first);
              }
              rng.collapse(true).select(true);
              if (opt.replaceStr !== undefined) {
                me.fireEvent('saveScene');
              }
              while (searchReplace(this, opt)) {
                num++;
                lastRng = me.selection.getRange();
                lastRng.collapse(opt.dir == -1);
              }
              if (num) {
                me.fireEvent('saveScene');
              }
            } else {
              if (opt.replaceStr !== undefined) {
                me.fireEvent('saveScene');
              }
              if (searchReplace(this, opt)) {
                num++;
                lastRng = me.selection.getRange();
                lastRng.collapse(opt.dir == -1);
              }
              if (num) {
                me.fireEvent('saveScene');
              }
            }
            return num;
          },
          notNeedUndo: 1,
        },
      },
      bindEvents: {
        clearlastSearchResult: function () {
          lastRng = null;
        },
      },
    };
  });
  UE.plugins['customstyle'] = function () {
    var me = this;
    me.setOpt({
      customstyle: [
        {
          tag: 'h1',
          name: 'tc',
          style:
            'font-size:32px;line-height:40px;font-weight:bold;border-bottom:#ccc 2px solid;padding:0 4px 0 0;text-align:center;',
        },
        {
          tag: 'h1',
          name: 'tl',
          style:
            'font-size:32px;line-height:40px;font-weight:bold;border-bottom:#ccc 2px solid;padding:0 4px 0 0;text-align:left;',
        },
        { tag: 'span', name: 'im', style: 'font-size:16px;font-style:italic;font-weight:bold;line-height:18px;' },
        {
          tag: 'span',
          name: 'hi',
          style: 'font-size:16px;font-style:italic;font-weight:bold;color:rgb(51, 153, 204);line-height:18px;',
        },
      ],
    });
    me.commands['customstyle'] = {
      execCommand: function (cmdName, obj) {
        var me = this,
          tagName = obj.tag,
          node = domUtils.findParent(
            me.selection.getStart(),
            function (node) {
              return node.getAttribute('label');
            },
            true,
          ),
          range,
          bk,
          tmpObj = {};
        for (var p in obj) {
          if (obj[p] !== undefined) tmpObj[p] = obj[p];
        }
        delete tmpObj.tag;
        if (node && node.getAttribute('label') == obj.label) {
          range = this.selection.getRange();
          bk = range.createBookmark();
          if (range.collapsed) {
            if (dtd.$block[node.tagName]) {
              var fillNode = me.document.createElement('p');
              domUtils.moveChild(node, fillNode);
              node.parentNode.insertBefore(fillNode, node);
              domUtils.remove(node);
            } else {
              domUtils.remove(node, true);
            }
          } else {
            var common = domUtils.getCommonAncestor(bk.start, bk.end),
              nodes = domUtils.getElementsByTagName(common, tagName);
            if (new RegExp(tagName, 'i').test(common.tagName)) {
              nodes.push(common);
            }
            for (var i = 0, ni; (ni = nodes[i++]); ) {
              if (ni.getAttribute('label') == obj.label) {
                var ps = domUtils.getPosition(ni, bk.start),
                  pe = domUtils.getPosition(ni, bk.end);
                if (
                  (ps & domUtils.POSITION_FOLLOWING || ps & domUtils.POSITION_CONTAINS) &&
                  (pe & domUtils.POSITION_PRECEDING || pe & domUtils.POSITION_CONTAINS)
                )
                  if (dtd.$block[tagName]) {
                    var fillNode = me.document.createElement('p');
                    domUtils.moveChild(ni, fillNode);
                    ni.parentNode.insertBefore(fillNode, ni);
                  }
                domUtils.remove(ni, true);
              }
            }
            node = domUtils.findParent(
              common,
              function (node) {
                return node.getAttribute('label') == obj.label;
              },
              true,
            );
            if (node) {
              domUtils.remove(node, true);
            }
          }
          range.moveToBookmark(bk).select();
        } else {
          if (dtd.$block[tagName]) {
            this.execCommand('paragraph', tagName, tmpObj, 'customstyle');
            range = me.selection.getRange();
            if (!range.collapsed) {
              range.collapse();
              node = domUtils.findParent(
                me.selection.getStart(),
                function (node) {
                  return node.getAttribute('label') == obj.label;
                },
                true,
              );
              var pNode = me.document.createElement('p');
              domUtils.insertAfter(node, pNode);
              domUtils.fillNode(me.document, pNode);
              range.setStart(pNode, 0).setCursor();
            }
          } else {
            range = me.selection.getRange();
            if (range.collapsed) {
              node = me.document.createElement(tagName);
              domUtils.setAttributes(node, tmpObj);
              range.insertNode(node).setStart(node, 0).setCursor();
              return;
            }
            bk = range.createBookmark();
            range.applyInlineStyle(tagName, tmpObj).moveToBookmark(bk).select();
          }
        }
      },
      queryCommandValue: function () {
        var parent = domUtils.filterNodeList(this.selection.getStartElementPath(), function (node) {
          return node.getAttribute('label');
        });
        return parent ? parent.getAttribute('label') : '';
      },
    };
    me.addListener('keyup', function (type, evt) {
      var keyCode = evt.keyCode || evt.which;
      if (keyCode == 32 || keyCode == 13) {
        var range = me.selection.getRange();
        if (range.collapsed) {
          var node = domUtils.findParent(
            me.selection.getStart(),
            function (node) {
              return node.getAttribute('label');
            },
            true,
          );
          if (node && dtd.$block[node.tagName] && domUtils.isEmptyNode(node)) {
            var p = me.document.createElement('p');
            domUtils.insertAfter(node, p);
            domUtils.fillNode(me.document, p);
            domUtils.remove(node);
            range.setStart(p, 0).setCursor();
          }
        }
      }
    });
  };
  UE.plugins['catchremoteimage'] = function () {
    var me = this,
      ajax = UE.ajax;
    if (me.options.catchRemoteImageEnable === false) {
      return;
    }
    me.setOpt({ catchRemoteImageEnable: false });
    var catcherLocalDomain = me.getOpt('catcherLocalDomain'),
      catcherActionUrl = me.getActionUrl(me.getOpt('catcherActionName')),
      catcherUrlPrefix = me.getOpt('catcherUrlPrefix'),
      catcherFieldName = me.getOpt('catcherFieldName');
    me.addListener('serverConfigLoaded', function () {
      catcherLocalDomain = me.getOpt('catcherLocalDomain');
      catcherActionUrl = me.getActionUrl(me.getOpt('catcherActionName'));
      catcherUrlPrefix = me.getOpt('catcherUrlPrefix');
      catcherFieldName = me.getOpt('catcherFieldName');
    });
    me.addListener('afterpaste', function () {
      me.fireEvent('catchremoteimage');
    });
    var catchRemoteImageCatching = false;
    function sendApi(imgs, callbacks) {
      var params = utils.serializeParam(me.queryCommandValue('serverparam')) || '',
        url = utils.formatUrl(catcherActionUrl + (catcherActionUrl.indexOf('?') === -1 ? '?' : '&') + params),
        isJsonp = utils.isCrossDomainUrl(url),
        opt = {
          method: 'POST',
          dataType: isJsonp ? 'jsonp' : '',
          timeout: 6e4,
          headers: me.options.serverHeaders || {},
          onsuccess: callbacks['success'],
          onerror: callbacks['error'],
        };
      opt[catcherFieldName] = imgs;
      ajax.request(url, opt);
    }
    function catchElement(type, ele, imageUrl) {
      sendApi([imageUrl], {
        success: function (r) {
          try {
            var info = r.state !== undefined ? r : eval('(' + r.responseText + ')');
          } catch (e) {
            return;
          }
          info = me.options.serverResponsePrepare(info);
          var oldSrc,
            newSrc,
            oldBgIMG,
            newBgIMG,
            list = info.list;
          var catchFailList = [];
          var catchSuccessList = [];
          var failIMG = me.options.themePath + me.options.theme + '/images/img-cracked.png';
          var loadingIMG = me.options.themePath + me.options.theme + '/images/spacer.gif';
          var cj = list[0];
          switch (type) {
            case 'image':
              oldSrc = ele.getAttribute('_src') || ele.src || '';
              if (cj.state === 'SUCCESS') {
                newSrc = catcherUrlPrefix + cj.url;
                domUtils.removeClasses(ele, 'uep-loading');
                domUtils.setAttributes(ele, { src: newSrc, _src: newSrc, 'data-catch-result': 'success' });
                catchSuccessList.push(ele);
              } else {
                domUtils.removeClasses(ele, 'uep-loading');
                domUtils.setAttributes(ele, { src: failIMG, _src: failIMG, 'data-catch-result': 'fail' });
                catchFailList.push(ele);
              }
              break;
            case 'background':
              oldBgIMG = ele.getAttribute('data-background') || '';
              if (cj.state === 'SUCCESS') {
                newBgIMG = catcherUrlPrefix + cj.url;
                ele.style.cssText = ele.style.cssText.replace(loadingIMG, newBgIMG);
                domUtils.removeAttributes(ele, 'data-background');
                domUtils.setAttributes(ele, { 'data-catch-result': 'success' });
                catchSuccessList.push(ele);
              } else {
                ele.style.cssText = ele.style.cssText.replace(loadingIMG, failIMG);
                domUtils.removeAttributes(ele, 'data-background');
                domUtils.setAttributes(ele, { 'data-catch-result': 'fail' });
                catchFailList.push(ele);
              }
              break;
          }
          me.fireEvent('catchremotesuccess', catchSuccessList, catchFailList);
          catchRemoteImageCatching = false;
          setTimeout(function () {
            me.fireEvent('catchremoteimage');
          }, 0);
        },
        error: function () {
          me.fireEvent('catchremoteerror');
          catchRemoteImageCatching = false;
          setTimeout(function () {
            me.fireEvent('catchremoteimage');
          }, 0);
        },
      });
    }
    function catchRemoteImage() {
      if (catchRemoteImageCatching) {
        return;
      }
      catchRemoteImageCatching = true;
      var loadingIMG = me.options.themePath + me.options.theme + '/images/spacer.gif',
        imgs = me.document.querySelectorAll('[style*="url"],img'),
        test = function (src, urls) {
          if (src.indexOf(location.host) !== -1 || /(^\.)|(^\/)/.test(src)) {
            return true;
          }
          if (urls) {
            for (var j = 0, url; (url = urls[j++]); ) {
              if (src.indexOf(url) !== -1) {
                return true;
              }
            }
          }
          return false;
        };
      for (var i = 0, ci; (ci = imgs[i++]); ) {
        if (
          ci.getAttribute('data-word-image') ||
          ci.getAttribute('data-catch-result') ||
          ci.getAttribute('data-formula-image')
        ) {
          continue;
        }
        if (ci.nodeName === 'IMG') {
          var src = ci.getAttribute('_src') || ci.src || '';
          if (/^(https?|ftp):/i.test(src) && !test(src, catcherLocalDomain)) {
            catchElement('image', ci, src);
            domUtils.setAttributes(ci, { class: 'uep-loading', _src: src, src: loadingIMG });
            return;
          }
        } else {
          var backgroundImageurl = ci.style.cssText.replace(/.*\s?url\([\'\"]?/, '').replace(/[\'\"]?\).*/, '');
          if (/^(https?|ftp):/i.test(backgroundImageurl) && !test(backgroundImageurl, catcherLocalDomain)) {
            catchElement('background', ci, backgroundImageurl);
            ci.style.cssText = ci.style.cssText.replace(backgroundImageurl, loadingIMG);
            domUtils.setAttributes(ci, { 'data-background': backgroundImageurl });
            return;
          }
        }
      }
      catchRemoteImageCatching = false;
    }
    me.addListener('catchremoteimage', function () {
      catchRemoteImage();
    });
  };
  UE.commands['insertparagraph'] = {
    execCommand: function (cmdName, front) {
      var me = this,
        range = me.selection.getRange(),
        start = range.startContainer,
        tmpNode;
      while (start) {
        if (domUtils.isBody(start)) {
          break;
        }
        tmpNode = start;
        start = start.parentNode;
      }
      if (tmpNode) {
        var p = me.document.createElement('p');
        if (front) {
          tmpNode.parentNode.insertBefore(p, tmpNode);
        } else {
          tmpNode.parentNode.insertBefore(p, tmpNode.nextSibling);
        }
        domUtils.fillNode(me.document, p);
        range.setStart(p, 0).setCursor(false, true);
      }
    },
  };
  UE.plugins['template'] = function () {
    UE.commands['template'] = {
      execCommand: function (cmd, obj) {
        obj.html && this.execCommand('inserthtml', obj.html);
      },
    };
    this.addListener('click', function (type, evt) {
      var el = evt.target || evt.srcElement,
        range = this.selection.getRange();
      var tnode = domUtils.findParent(
        el,
        function (node) {
          if (node.className && domUtils.hasClass(node, 'ue_t')) {
            return node;
          }
        },
        true,
      );
      tnode && range.selectNode(tnode).shrinkBoundary().select();
    });
    this.addListener('keydown', function (type, evt) {
      var range = this.selection.getRange();
      if (!range.collapsed) {
        if (!evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey) {
          var tnode = domUtils.findParent(
            range.startContainer,
            function (node) {
              if (node.className && domUtils.hasClass(node, 'ue_t')) {
                return node;
              }
            },
            true,
          );
          if (tnode) {
            domUtils.removeClasses(tnode, ['ue_t']);
          }
        }
      }
    });
  };
  UE.plugin.register('autoupload', function () {
    function sendAndInsertFile(file, editor) {
      var me = editor;
      var fieldName,
        urlPrefix,
        maxSize,
        allowFiles,
        actionUrl,
        loadingHtml,
        errorHandler,
        successHandler,
        filetype = /image\/\w+/i.test(file.type) ? 'image' : 'file',
        fileExt = UE.plus.fileExt(file.name),
        loadingId = 'loading_' + (+new Date()).toString(36);
      fieldName = me.getOpt(filetype + 'FieldName');
      urlPrefix = me.getOpt(filetype + 'UrlPrefix');
      maxSize = me.getOpt(filetype + 'MaxSize');
      allowFiles = me.getOpt(filetype + 'AllowFiles');
      actionUrl = me.getActionUrl(me.getOpt(filetype + 'ActionName'));
      errorHandler = function (title) {
        var loader = me.document.getElementById(loadingId);
        loader && domUtils.remove(loader);
        me.fireEvent('showmessage', { id: loadingId, content: title, type: 'error', timeout: 4e3 });
      };
      if (filetype === 'image') {
        loadingHtml =
          '<img class="uep-loading" id="' +
          loadingId +
          '" src="' +
          me.options.themePath +
          me.options.theme +
          '/images/spacer.gif">';
        successHandler = function (data) {
          var link = urlPrefix + data.url,
            loader = me.document.getElementById(loadingId);
          if (loader) {
            domUtils.removeClasses(loader, 'uep-loading');
            loader.setAttribute('src', link);
            loader.setAttribute('_src', link);
            loader.setAttribute('alt', data.original || '');
            loader.removeAttribute('id');
            me.trigger('contentchange', loader);
          }
        };
      } else {
        loadingHtml =
          '<p>' +
          '<img class="uep-loading" id="' +
          loadingId +
          '" src="' +
          me.options.themePath +
          me.options.theme +
          '/images/spacer.gif">' +
          '</p>';
        successHandler = function (data) {
          var link = urlPrefix + data.url,
            loader = me.document.getElementById(loadingId);
          var rng = me.selection.getRange(),
            bk = rng.createBookmark();
          rng.selectNode(loader).select();
          me.execCommand('insertfile', { url: link });
          rng.moveToBookmark(bk).select();
        };
      }
      me.execCommand('inserthtml', loadingHtml);
      if (!me.getOpt(filetype + 'ActionName')) {
        errorHandler(me.getLang('autoupload.errorLoadConfig'));
        return;
      }
      if (file.size > maxSize) {
        errorHandler(me.getLang('autoupload.exceedSizeError'));
        return;
      }
      var fileext = file.name ? file.name.substr(file.name.lastIndexOf('.')) : '';
      if (
        (fileext && filetype != 'image') ||
        (allowFiles && (allowFiles.join('') + '.').indexOf(fileext.toLowerCase() + '.') == -1)
      ) {
        errorHandler(me.getLang('autoupload.exceedTypeError'));
        return;
      }
      var upload = function (file) {
        if (me.getOpt('uploadServiceEnable')) {
          me.getOpt('uploadServiceUpload')(
            'image',
            file,
            {
              success: function (res) {
                successHandler(res);
              },
              error: function (err) {
                errorHandler(me.getLang('autoupload.loadError') + ' : ' + err);
              },
              progress: function (percent) {},
            },
            { from: 'paste' },
          );
          return;
        }
        var formData = new FormData();
        formData.append(fieldName, file, file.name);
        UE.api
          .requestAction(me, me.getOpt(filetype + 'ActionName'), { data: formData })
          .then(function (res) {
            successHandler(me.getOpt('serverResponsePrepare')(res.data));
          })
          .catch(function (err) {
            errorHandler(me.getLang('autoupload.loadError') + ' : ' + err);
          });
      };
      var imageCompressEnable = me.getOpt('imageCompressEnable'),
        imageMaxSize = me.getOpt('imageMaxSize'),
        imageCompressBorder = me.getOpt('imageCompressBorder');
      if ('image' === filetype && imageCompressEnable && ['jpg', 'jpeg', 'png'].includes(fileExt)) {
        UE.image
          .compress(file, { maxSizeMB: imageMaxSize / 1024 / 1024, maxWidthOrHeight: imageCompressBorder })
          .then(function (compressedFile) {
            if (me.options.debug) {
              console.log('AutoUpload.CompressImage', ((compressedFile.size / file.size) * 100).toFixed(2) + '%');
            }
            upload(compressedFile);
          })
          .catch(function (err) {
            console.error('AutoUpload.CompressImage.error', err);
            upload(file);
          });
      } else {
        upload(file);
      }
    }
    function getPasteImage(e) {
      var images = [];
      if (e.clipboardData && e.clipboardData.items) {
        var items = e.clipboardData.items;
        for (let i = 0; i < items.length; i++) {
          if (items[i].type.indexOf('image') !== -1) {
            images.push(items[i]);
          }
        }
      }
      return images;
    }
    function getDropImage(e) {
      return e.dataTransfer && e.dataTransfer.files ? e.dataTransfer.files : null;
    }
    return {
      outputRule: function (root) {
        utils.each(root.getNodesByTagName('img'), function (n) {
          if (/\b(uep\-loading\-error)|(bloaderrorclass)\b/.test(n.getAttr('class'))) {
            n.parentNode.removeChild(n);
          }
        });
        utils.each(root.getNodesByTagName('p'), function (n) {
          if (/\bloadpara\b/.test(n.getAttr('class'))) {
            n.parentNode.removeChild(n);
          }
        });
      },
      bindEvents: {
        defaultOptions: { enableDragUpload: true, enablePasteUpload: true },
        ready: function (e) {
          var me = this;
          if (window.FormData && window.FileReader) {
            var handler = function (e) {
              var hasImg = false,
                items;
              items = e.type === 'paste' ? getPasteImage(e) : getDropImage(e);
              if (items) {
                var len = items.length,
                  file;
                while (len--) {
                  file = items[len];
                  if (file.getAsFile) file = file.getAsFile();
                  if (file && file.size > 0) {
                    sendAndInsertFile(file, me);
                    hasImg = true;
                  }
                }
                hasImg && e.preventDefault();
              }
            };
            if (me.getOpt('enablePasteUpload') !== false) {
              domUtils.on(me.body, 'paste ', handler);
            }
            if (me.getOpt('enableDragUpload') !== false) {
              domUtils.on(me.body, 'drop', handler);
              domUtils.on(me.body, 'dragover', function (e) {
                if (e.dataTransfer.types[0] == 'Files') {
                  e.preventDefault();
                }
              });
            } else {
              if (browser.gecko) {
                domUtils.on(me.body, 'drop', function (e) {
                  if (getDropImage(e)) {
                    e.preventDefault();
                  }
                });
              }
            }
            utils.cssRule(
              'loading',
              ".uep-loading{display:inline-block;cursor:default;background: url('" +
                this.options.themePath +
                this.options.theme +
                "/images/loading.gif') no-repeat center center transparent;border-radius:3px;outline:1px solid #EEE;margin-left:1px;height:22px;width:22px;}\n" +
                ".uep-loading-error{display:inline-block;cursor:default;background: url('" +
                this.options.themePath +
                this.options.theme +
                "/images/loaderror.png') no-repeat center center transparent;border-radius:3px;outline:1px solid #EEE;margin-right:1px;height:22px;width:22px;" +
                '}',
              this.document,
            );
          }
        },
      },
    };
  });
  UE.plugin.register('section', function () {
    function Section(option) {
      this.tag = '';
      ((this.level = -1), (this.dom = null));
      this.nextSection = null;
      this.previousSection = null;
      this.parentSection = null;
      this.startAddress = [];
      this.endAddress = [];
      this.children = [];
    }
    function getSection(option) {
      var section = new Section();
      return utils.extend(section, option);
    }
    function getNodeFromAddress(startAddress, root) {
      var current = root;
      for (var i = 0; i < startAddress.length; i++) {
        if (!current.childNodes) return null;
        current = current.childNodes[startAddress[i]];
      }
      return current;
    }
    var me = this;
    return {
      bindMultiEvents: {
        type: 'aftersetcontent afterscencerestore',
        handler: function () {
          me.fireEvent('updateSections');
        },
      },
      bindEvents: {
        ready: function () {
          me.fireEvent('updateSections');
          domUtils.on(me.body, 'drop paste', function () {
            me.fireEvent('updateSections');
          });
        },
        afterexeccommand: function (type, cmd) {
          if (cmd == 'paragraph') {
            me.fireEvent('updateSections');
          }
        },
        keyup: function (type, e) {
          var me = this,
            range = me.selection.getRange();
          if (range.collapsed != true) {
            me.fireEvent('updateSections');
          } else {
            var keyCode = e.keyCode || e.which;
            if (keyCode == 13 || keyCode == 8 || keyCode == 46) {
              me.fireEvent('updateSections');
            }
          }
        },
      },
      commands: {
        getsections: {
          execCommand: function (cmd, levels) {
            var levelFn = levels || ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
            for (var i = 0; i < levelFn.length; i++) {
              if (typeof levelFn[i] == 'string') {
                levelFn[i] = (function (fn) {
                  return function (node) {
                    return node.tagName == fn.toUpperCase();
                  };
                })(levelFn[i]);
              } else if (typeof levelFn[i] != 'function') {
                levelFn[i] = function (node) {
                  return null;
                };
              }
            }
            function getSectionLevel(node) {
              for (var i = 0; i < levelFn.length; i++) {
                if (levelFn[i](node)) return i;
              }
              return -1;
            }
            var me = this,
              Directory = getSection({ level: -1, title: 'root' }),
              previous = Directory;
            function traversal(node, Directory) {
              var level,
                tmpSection = null,
                parent,
                child,
                children = node.childNodes;
              for (var i = 0, len = children.length; i < len; i++) {
                child = children[i];
                level = getSectionLevel(child);
                if (level >= 0) {
                  var address = me.selection.getRange().selectNode(child).createAddress(true).startAddress,
                    current = getSection({
                      tag: child.tagName,
                      title: child.innerText || child.textContent || '',
                      level: level,
                      dom: child,
                      startAddress: utils.clone(address, []),
                      endAddress: utils.clone(address, []),
                      children: [],
                    });
                  previous.nextSection = current;
                  current.previousSection = previous;
                  parent = previous;
                  while (level <= parent.level) {
                    parent = parent.parentSection;
                  }
                  current.parentSection = parent;
                  parent.children.push(current);
                  tmpSection = previous = current;
                } else {
                  child.nodeType === 1 && traversal(child, Directory);
                  tmpSection && tmpSection.endAddress[tmpSection.endAddress.length - 1]++;
                }
              }
            }
            traversal(me.body, Directory);
            return Directory;
          },
          notNeedUndo: true,
        },
        movesection: {
          execCommand: function (cmd, sourceSection, targetSection, isAfter) {
            var me = this,
              targetAddress,
              target;
            if (!sourceSection || !targetSection || targetSection.level == -1) return;
            targetAddress = isAfter ? targetSection.endAddress : targetSection.startAddress;
            target = getNodeFromAddress(targetAddress, me.body);
            if (
              !targetAddress ||
              !target ||
              isContainsAddress(sourceSection.startAddress, sourceSection.endAddress, targetAddress)
            )
              return;
            var startNode = getNodeFromAddress(sourceSection.startAddress, me.body),
              endNode = getNodeFromAddress(sourceSection.endAddress, me.body),
              current,
              nextNode;
            if (isAfter) {
              current = endNode;
              while (current && !(domUtils.getPosition(startNode, current) & domUtils.POSITION_FOLLOWING)) {
                nextNode = current.previousSibling;
                domUtils.insertAfter(target, current);
                if (current == startNode) break;
                current = nextNode;
              }
            } else {
              current = startNode;
              while (current && !(domUtils.getPosition(current, endNode) & domUtils.POSITION_FOLLOWING)) {
                nextNode = current.nextSibling;
                target.parentNode.insertBefore(current, target);
                if (current == endNode) break;
                current = nextNode;
              }
            }
            me.fireEvent('updateSections');
            function isContainsAddress(startAddress, endAddress, addressTarget) {
              var isAfterStartAddress = false,
                isBeforeEndAddress = false;
              for (var i = 0; i < startAddress.length; i++) {
                if (i >= addressTarget.length) break;
                if (addressTarget[i] > startAddress[i]) {
                  isAfterStartAddress = true;
                  break;
                } else if (addressTarget[i] < startAddress[i]) {
                  break;
                }
              }
              for (var i = 0; i < endAddress.length; i++) {
                if (i >= addressTarget.length) break;
                if (addressTarget[i] < startAddress[i]) {
                  isBeforeEndAddress = true;
                  break;
                } else if (addressTarget[i] > startAddress[i]) {
                  break;
                }
              }
              return isAfterStartAddress && isBeforeEndAddress;
            }
          },
        },
        deletesection: {
          execCommand: function (cmd, section, keepChildren) {
            var me = this;
            if (!section) return;
            function getNodeFromAddress(startAddress) {
              var current = me.body;
              for (var i = 0; i < startAddress.length; i++) {
                if (!current.childNodes) return null;
                current = current.childNodes[startAddress[i]];
              }
              return current;
            }
            var startNode = getNodeFromAddress(section.startAddress),
              endNode = getNodeFromAddress(section.endAddress),
              current = startNode,
              nextNode;
            if (!keepChildren) {
              while (
                current &&
                domUtils.inDoc(endNode, me.document) &&
                !(domUtils.getPosition(current, endNode) & domUtils.POSITION_FOLLOWING)
              ) {
                nextNode = current.nextSibling;
                domUtils.remove(current);
                current = nextNode;
              }
            } else {
              domUtils.remove(current);
            }
            me.fireEvent('updateSections');
          },
        },
        selectsection: {
          execCommand: function (cmd, section) {
            if (!section && !section.dom) return false;
            var me = this,
              range = me.selection.getRange(),
              address = {
                startAddress: utils.clone(section.startAddress, []),
                endAddress: utils.clone(section.endAddress, []),
              };
            address.endAddress[address.endAddress.length - 1]++;
            range.moveToAddress(address).select().scrollToView();
            return true;
          },
          notNeedUndo: true,
        },
        scrolltosection: {
          execCommand: function (cmd, section) {
            if (!section && !section.dom) return false;
            var me = this,
              range = me.selection.getRange(),
              address = { startAddress: section.startAddress, endAddress: section.endAddress };
            address.endAddress[address.endAddress.length - 1]++;
            range.moveToAddress(address).scrollToView();
            return true;
          },
          notNeedUndo: true,
        },
      },
    };
  });
  UE.plugin.register('simpleupload', function () {
    var me = this,
      isLoaded = false,
      containerBtn;
    function initUploadBtn() {
      var input = document.createElement('input');
      input.style.cssText =
        'position:absolute;top:0;left:0;width:100%;height:100%;cursor:pointer;font-size:0;opacity:0;';
      input.type = 'file';
      input.accept = me.getOpt('imageAllowFiles').join(',');
      containerBtn.appendChild(input);
      domUtils.on(input, 'click', function (e) {
        var toolbarCallback = me.getOpt('toolbarCallback');
        if (toolbarCallback) {
          if (true === toolbarCallback('simpleupload', me)) {
            e.stopPropagation();
            e.preventDefault();
          }
        }
      });
      domUtils.on(input, 'change', function (e) {
        var state = me.queryCommandState('simpleupload');
        if (state === -1) {
          return;
        }
        if (!input.value) {
          return;
        }
        var loadingId = UE.dialog.loadingPlaceholder(me);
        if (!me.getOpt('imageActionName')) {
          UE.dialog.removeLoadingPlaceholder(me, loadingId);
          UE.dialog.tipError(me, me.getLang('autoupload.errorLoadConfig'));
          return;
        }
        var allowFiles = me.getOpt('imageAllowFiles');
        var filename = input.value,
          fileext = filename ? filename.substr(filename.lastIndexOf('.')) : '';
        if (!fileext || (allowFiles && (allowFiles.join('') + '.').indexOf(fileext.toLowerCase() + '.') === -1)) {
          UE.dialog.removeLoadingPlaceholder(me, loadingId);
          UE.dialog.tipError(me, me.getLang('autoupload.exceedTypeError'));
          return;
        }
        var successHandler = function (res) {
          const loader = me.document.getElementById(loadingId);
          domUtils.removeClasses(loader, 'uep-loading');
          const link = me.options.imageUrlPrefix + res.url;
          loader.setAttribute('src', link);
          loader.setAttribute('_src', link);
          loader.setAttribute('alt', res.original || '');
          loader.removeAttribute('id');
          me.fireEvent('contentchange');
          me.fireEvent('uploadsuccess', { res: res, type: 'image' });
        };
        var errorHandler = function (err) {
          UE.dialog.removeLoadingPlaceholder(me, loadingId);
          UE.dialog.tipError(me, err);
        };
        var upload = function (file) {
          if (me.getOpt('uploadServiceEnable')) {
            me.getOpt('uploadServiceUpload')(
              'image',
              file,
              {
                success: function (res) {
                  successHandler(res);
                },
                error: function (err) {
                  errorHandler(me.getLang('simpleupload.loadError') + ' : ' + err);
                },
                progress: function (percent) {},
              },
              { from: 'upload' },
            );
            return;
          }
          const formData = new FormData();
          formData.append(me.getOpt('imageFieldName'), file, file.name);
          UE.api
            .requestAction(me, me.getOpt('imageActionName'), { data: formData })
            .then(function (res) {
              res = me.getOpt('serverResponsePrepare')(res.data);
              if ('SUCCESS' === res.state && res.url) {
                successHandler(res);
              } else {
                errorHandler(res.state);
              }
              input.value = '';
            })
            .catch(function (err) {
              errorHandler(err);
              input.value = '';
            });
        };
        var file = input.files[0];
        var fileExt = UE.plus.fileExt(file.name);
        var imageCompressEnable = me.getOpt('imageCompressEnable'),
          imageMaxSize = me.getOpt('imageMaxSize'),
          imageCompressBorder = me.getOpt('imageCompressBorder');
        if (imageCompressEnable && ['jpg', 'jpeg', 'png'].includes(fileExt)) {
          UE.image
            .compress(file, { maxSizeMB: imageMaxSize / 1024 / 1024, maxWidthOrHeight: imageCompressBorder })
            .then(function (compressedFile) {
              if (me.options.debug) {
                console.log(
                  'UEditorPlus.SimpleUpload.CompressImage',
                  ((compressedFile.size / file.size) * 100).toFixed(2) + '%',
                );
              }
              upload(compressedFile);
            })
            .catch(function (err) {
              console.error('UEditorPlus.SimpleUpload.CompressImage.error', err);
              upload(file);
            });
        } else {
          upload(file);
        }
      });
      var stateTimer;
      me.addListener('selectionchange', function () {
        clearTimeout(stateTimer);
        stateTimer = setTimeout(function () {
          var state = me.queryCommandState('simpleupload');
          if (state === -1) {
            input.disabled = 'disabled';
          } else {
            input.disabled = false;
          }
        }, 400);
      });
      isLoaded = true;
    }
    return {
      bindEvents: {
        ready: function () {
          utils.cssRule(
            'loading',
            ".uep-loading{display:inline-block;cursor:default;background: url('" +
              this.options.themePath +
              this.options.theme +
              "/images/loading.gif') no-repeat center center transparent;border-radius:3px;outline:1px solid #EEE;margin-right:1px;height:22px;width:22px;}\n" +
              ".uep-loading-error{display:inline-block;cursor:default;background: url('" +
              this.options.themePath +
              this.options.theme +
              "/images/loaderror.png') no-repeat center center transparent;border-radius:3px;outline:1px solid #EEE;margin-right:1px;height:22px;width:22px;" +
              '}',
            this.document,
          );
        },
        simpleuploadbtnready: function (type, container) {
          containerBtn = container;
          me.afterConfigReady(initUploadBtn);
        },
      },
      outputRule: function (root) {
        utils.each(root.getNodesByTagName('img'), function (n) {
          if (/\b(uep\-loading\-error)|(bloaderrorclass)\b/.test(n.getAttr('class'))) {
            n.parentNode.removeChild(n);
          }
        });
      },
      commands: {
        simpleupload: {
          queryCommandState: function () {
            return isLoaded ? 0 : -1;
          },
        },
      },
    };
  });
  UE.plugin.register('serverparam', function () {
    var me = this,
      serverParam = {};
    return {
      commands: {
        serverparam: {
          execCommand: function (cmd, key, value) {
            if (key === undefined || key === null) {
              serverParam = {};
            } else if (utils.isString(key)) {
              if (value === undefined || value === null) {
                delete serverParam[key];
              } else {
                serverParam[key] = value;
              }
            } else if (utils.isObject(key)) {
              utils.extend(serverParam, key, false);
            } else if (utils.isFunction(key)) {
              utils.extend(serverParam, key(), false);
            }
          },
          queryCommandValue: function () {
            return serverParam || {};
          },
        },
      },
    };
  });
  UE.plugin.register('insertfile', function () {
    var me = this;
    function getFileIcon(url) {
      var ext = url.substr(url.lastIndexOf('.') + 1).toLowerCase(),
        maps = {
          ai: 'ai.svg',
          apk: 'apk.svg',
          chm: 'chm.svg',
          css: 'css.svg',
          doc: 'doc.svg',
          docx: 'docx.svg',
          dwg: 'dwg.svg',
          gif: 'gif.svg',
          html: 'html.svg',
          jpeg: 'jpeg.svg',
          jpg: 'jpg.svg',
          log: 'log.svg',
          mp3: 'mp3.svg',
          mp4: 'mp4.svg',
          pdf: 'pdf.svg',
          png: 'png.svg',
          ppt: 'ppt.svg',
          pptx: 'pptx.svg',
          psd: 'psd.svg',
          rar: 'rar.svg',
          svg: 'svg.svg',
          torrent: 'torrent.svg',
          txt: 'txt.svg',
          unknown: 'unknown.svg',
          xls: 'xls.svg',
          xlsx: 'xlsx.svg',
          zip: 'zip.svg',
        };
      return maps[ext] ? maps[ext] : maps['unknown'];
    }
    return {
      commands: {
        insertfile: {
          execCommand: function (command, filelist) {
            filelist = utils.isArray(filelist) ? filelist : [filelist];
            if (me.fireEvent('beforeinsertfile', filelist) === true) {
              return;
            }
            var i,
              item,
              icon,
              title,
              html = '',
              URL = me.getOpt('UEDITOR_HOME_URL'),
              iconDir = me.options.themePath + me.options.theme + '/exts/';
            for (i = 0; i < filelist.length; i++) {
              item = filelist[i];
              icon = iconDir + getFileIcon(item.url);
              title = item.title || item.url.substr(item.url.lastIndexOf('/') + 1);
              html +=
                '<p>' +
                '<a style="background:#EEE;padding:10px;border-radius:5px;line-height:1.5em;display:inline-flex;align-items:center;" href="' +
                item.url +
                '" title="' +
                title +
                '" target="_blank">' +
                '<img style="vertical-align:middle;margin-right:0.5em;height:1.5em;" src="' +
                icon +
                '" _src="' +
                icon +
                '" />' +
                '<span style="color:#111111;line-height:1.5em;flex-grow:1;">' +
                title +
                '</span>' +
                '</a>' +
                '</p>';
            }
            me.execCommand('insertHtml', html);
            me.fireEvent('afterinsertfile', filelist);
          },
        },
      },
    };
  });
  UE.plugins['markdown-shortcut'] = function () {
    if (!UE.browser.chrome) {
      return;
    }
    const me = this;
    const getCleanHtml = function (node) {
      let html = node.innerHTML;
      html = html.replace(/[\u200b]*/g, '');
      return html;
    };
    let shortCuts = [];
    for (let i = 1; i <= 6; i++) {
      const regExp = new RegExp('^\\t?' + Array(i + 1).join('#') + '(\\s|&nbsp;)');
      (function (command) {
        shortCuts.push({
          name: 'Head' + i,
          tagName: ['P'],
          key: [' '],
          offset: [i + 1, i + 2],
          match: [regExp],
          callback: function (param) {
            me.__hasEnterExecCommand = true;
            me.execCommand('paragraph', command);
            let range = me.selection.getRange();
            let node = range.startContainer;
            let html = getCleanHtml(node);
            html = html.replace(regExp, '');
            if (!html) {
              html = domUtils.fillChar;
            }
            node.innerHTML = html;
            me.__hasEnterExecCommand = false;
          },
        });
      })('h' + i);
    }
    me.on('ready', function () {
      domUtils.on(me.body, 'keyup', function (e) {
        let range = me.selection.getRange();
        if (range.endOffset !== range.startOffset) {
          return;
        }
        let key = e.key;
        let offset = range.startOffset;
        const node = range.startContainer.parentNode;
        let html = getCleanHtml(node);
        let tagName = node.tagName;
        for (let s of shortCuts) {
          if (!s.tagName.includes(tagName)) {
            continue;
          }
          if (!s.key.includes(key)) {
            continue;
          }
          if (!s.offset.includes(offset)) {
            continue;
          }
          for (let m of s.match) {
            let match = html.match(m);
            if (match) {
              s.callback({ node: node });
              break;
            }
          }
        }
      });
    });
  };
  UE.plugins['quick-operate'] = function () {
    if (!UE.browser.chrome) {
      return;
    }
    return;
  };
  var baidu = baidu || {};
  baidu.editor = baidu.editor || {};
  UE.ui = baidu.editor.ui = {};
  (function () {
    var browser = baidu.editor.browser,
      domUtils = baidu.editor.dom.domUtils;
    var magic = '$EDITORUI';
    var root = (window[magic] = {});
    var uidMagic = 'ID' + magic;
    var uidCount = 0;
    var uiUtils = (baidu.editor.ui.uiUtils = {
      uid: function (obj) {
        return obj ? obj[uidMagic] || (obj[uidMagic] = ++uidCount) : ++uidCount;
      },
      hook: function (fn, callback) {
        var dg;
        if (fn && fn._callbacks) {
          dg = fn;
        } else {
          dg = function () {
            var q;
            if (fn) {
              q = fn.apply(this, arguments);
            }
            var callbacks = dg._callbacks;
            var k = callbacks.length;
            while (k--) {
              var r = callbacks[k].apply(this, arguments);
              if (q === undefined) {
                q = r;
              }
            }
            return q;
          };
          dg._callbacks = [];
        }
        dg._callbacks.push(callback);
        return dg;
      },
      createElementByHtml: function (html) {
        var el = document.createElement('div');
        el.innerHTML = html;
        el = el.firstChild;
        el.parentNode.removeChild(el);
        return el;
      },
      getViewportElement: function () {
        return browser.ie && browser.quirks ? document.body : document.documentElement;
      },
      getClientRect: function (element) {
        var bcr;
        try {
          bcr = element.getBoundingClientRect();
        } catch (e) {
          bcr = { left: 0, top: 0, height: 0, width: 0 };
        }
        var rect = {
          left: Math.round(bcr.left),
          top: Math.round(bcr.top),
          height: Math.round(bcr.bottom - bcr.top),
          width: Math.round(bcr.right - bcr.left),
        };
        var doc;
        while ((doc = element.ownerDocument) !== document && (element = domUtils.getWindow(doc).frameElement)) {
          bcr = element.getBoundingClientRect();
          rect.left += bcr.left;
          rect.top += bcr.top;
        }
        rect.bottom = rect.top + rect.height;
        rect.right = rect.left + rect.width;
        return rect;
      },
      getViewportRect: function () {
        var viewportEl = uiUtils.getViewportElement();
        var width = (window.innerWidth || viewportEl.clientWidth) | 0;
        var height = (window.innerHeight || viewportEl.clientHeight) | 0;
        return { left: 0, top: 0, height: height, width: width, bottom: height, right: width };
      },
      setViewportOffset: function (element, offset) {
        var rect;
        var fixedLayer = uiUtils.getFixedLayer();
        if (element.parentNode === fixedLayer) {
          element.style.left = offset.left + 'px';
          element.style.top = offset.top + 'px';
        } else {
          domUtils.setViewportOffset(element, offset);
        }
      },
      getEventOffset: function (evt) {
        var el = evt.target || evt.srcElement;
        var rect = uiUtils.getClientRect(el);
        var offset = uiUtils.getViewportOffsetByEvent(evt);
        return { left: offset.left - rect.left, top: offset.top - rect.top };
      },
      getViewportOffsetByEvent: function (evt) {
        var el = evt.target || evt.srcElement;
        var frameEl = domUtils.getWindow(el).frameElement;
        var offset = { left: evt.clientX, top: evt.clientY };
        if (frameEl && el.ownerDocument !== document) {
          var rect = uiUtils.getClientRect(frameEl);
          offset.left += rect.left;
          offset.top += rect.top;
        }
        return offset;
      },
      setGlobal: function (id, obj) {
        root[id] = obj;
        return magic + '["' + id + '"]';
      },
      unsetGlobal: function (id) {
        delete root[id];
      },
      copyAttributes: function (tgt, src) {
        var attributes = src.attributes;
        var k = attributes.length;
        while (k--) {
          var attrNode = attributes[k];
          if (attrNode.nodeName != 'style' && attrNode.nodeName != 'class' && (!browser.ie || attrNode.specified)) {
            tgt.setAttribute(attrNode.nodeName, attrNode.nodeValue);
          }
        }
        if (src.className) {
          domUtils.addClass(tgt, src.className);
        }
        if (src.style.cssText) {
          tgt.style.cssText += ';' + src.style.cssText;
        }
      },
      removeStyle: function (el, styleName) {
        if (el.style.removeProperty) {
          el.style.removeProperty(styleName);
        } else if (el.style.removeAttribute) {
          el.style.removeAttribute(styleName);
        } else throw '';
      },
      contains: function (elA, elB) {
        return (
          elA && elB && (elA === elB ? false : elA.contains ? elA.contains(elB) : elA.compareDocumentPosition(elB) & 16)
        );
      },
      startDrag: function (evt, callbacks, doc) {
        var doc = doc || document;
        var startX = evt.clientX;
        var startY = evt.clientY;
        function handleMouseMove(evt) {
          var x = evt.clientX - startX;
          var y = evt.clientY - startY;
          callbacks.ondragmove(x, y, evt);
          if (evt.stopPropagation) {
            evt.stopPropagation();
          } else {
            evt.cancelBubble = true;
          }
        }
        if (doc.addEventListener) {
          function handleMouseUp(evt) {
            doc.removeEventListener('mousemove', handleMouseMove, true);
            doc.removeEventListener('mouseup', handleMouseUp, true);
            window.removeEventListener('mouseup', handleMouseUp, true);
            callbacks.ondragstop();
          }
          doc.addEventListener('mousemove', handleMouseMove, true);
          doc.addEventListener('mouseup', handleMouseUp, true);
          window.addEventListener('mouseup', handleMouseUp, true);
          evt.preventDefault();
        } else {
          var elm = evt.srcElement;
          elm.setCapture();
          function releaseCaptrue() {
            elm.releaseCapture();
            elm.detachEvent('onmousemove', handleMouseMove);
            elm.detachEvent('onmouseup', releaseCaptrue);
            elm.detachEvent('onlosecaptrue', releaseCaptrue);
            callbacks.ondragstop();
          }
          elm.attachEvent('onmousemove', handleMouseMove);
          elm.attachEvent('onmouseup', releaseCaptrue);
          elm.attachEvent('onlosecaptrue', releaseCaptrue);
          evt.returnValue = false;
        }
        callbacks.ondragstart();
      },
      getFixedLayer: function () {
        var layer = document.getElementById('edui_fixedlayer');
        if (layer == null) {
          layer = document.createElement('div');
          layer.id = 'edui_fixedlayer';
          document.body.appendChild(layer);
          if (browser.ie && browser.version <= 8) {
            layer.style.position = 'absolute';
            bindFixedLayer();
            setTimeout(updateFixedOffset);
          } else {
            layer.style.position = 'fixed';
          }
          layer.style.left = '0';
          layer.style.top = '0';
          layer.style.width = '0';
          layer.style.height = '0';
          layer.style.margin = '0';
        }
        return layer;
      },
      makeUnselectable: function (element) {
        if (browser.opera || (browser.ie && browser.version < 9)) {
          element.unselectable = 'on';
          if (element.hasChildNodes()) {
            for (var i = 0; i < element.childNodes.length; i++) {
              if (element.childNodes[i].nodeType === 1) {
                uiUtils.makeUnselectable(element.childNodes[i]);
              }
            }
          }
        } else {
          if (element.style.MozUserSelect !== undefined) {
            element.style.MozUserSelect = 'none';
          } else if (element.style.WebkitUserSelect !== undefined) {
            element.style.WebkitUserSelect = 'none';
          } else if (element.style.KhtmlUserSelect !== undefined) {
            element.style.KhtmlUserSelect = 'none';
          }
        }
      },
    });
    function updateFixedOffset() {
      var layer = document.getElementById('edui_fixedlayer');
      uiUtils.setViewportOffset(layer, { left: 0, top: 0 });
    }
    function bindFixedLayer(adjOffset) {
      domUtils.on(window, 'scroll', updateFixedOffset);
      domUtils.on(window, 'resize', baidu.editor.utils.defer(updateFixedOffset, 0, true));
    }
  })();
  (function () {
    var utils = baidu.editor.utils,
      uiUtils = baidu.editor.ui.uiUtils,
      EventBase = baidu.editor.EventBase,
      UIBase = (baidu.editor.ui.UIBase = function () {});
    UIBase.prototype = {
      el: null,
      className: '',
      uiName: '',
      initOptions: function (options) {
        var me = this;
        for (var k in options) {
          me[k] = options[k];
        }
        this.id = this.id || 'edui' + uiUtils.uid();
      },
      initUIBase: function () {
        this._globalKey = utils.unhtml(uiUtils.setGlobal(this.id, this));
      },
      render: function (holder) {
        var html = this.renderHtml();
        var el = uiUtils.createElementByHtml(html);
        var list = domUtils.getElementsByTagName(el, '*');
        var theme = 'edui-' + (this.theme || this.editor.options.theme);
        var layer = document.getElementById('edui_fixedlayer');
        for (var i = 0, node; (node = list[i++]); ) {
          domUtils.addClass(node, theme);
        }
        domUtils.addClass(el, theme);
        if (layer) {
          layer.className = '';
          domUtils.addClass(layer, theme);
        }
        var seatEl = this.getDom();
        if (seatEl != null) {
          seatEl.parentNode.replaceChild(el, seatEl);
          uiUtils.copyAttributes(el, seatEl);
        } else {
          if (typeof holder == 'string') {
            holder = document.getElementById(holder);
          }
          holder = holder || uiUtils.getFixedLayer();
          domUtils.addClass(holder, theme);
          holder.appendChild(el);
        }
        this.el = el;
        this.postRender();
      },
      getDom: function (name) {
        if (!name) {
          return document.getElementById(this.id);
        } else {
          return document.getElementById(this.id + '_' + name);
        }
      },
      postRender: function () {
        this.fireEvent('postrender');
      },
      getHtmlTpl: function () {
        return '';
      },
      formatHtml: function (tpl) {
        var prefix = 'edui-' + this.uiName;
        return tpl
          .replace(/##/g, this.id)
          .replace(/%%-/g, this.uiName ? prefix + '-' : '')
          .replace(/%%/g, (this.uiName ? prefix : '') + ' ' + this.className)
          .replace(/\$\$/g, this._globalKey);
      },
      renderHtml: function () {
        return this.formatHtml(this.getHtmlTpl());
      },
      dispose: function () {
        var box = this.getDom();
        if (box) baidu.editor.dom.domUtils.remove(box);
        uiUtils.unsetGlobal(this.id);
      },
      uiIsShow: true,
      uiShowStyleBackupValue: null,
      uiShow: function (enable) {
        if (enable) {
          if (this.uiIsShow) {
            return;
          }
          this.getDom().style.display = this.uiShowStyleBackupValue;
          this.uiIsShow = true;
        } else {
          if (!this.uiIsShow) {
            return;
          }
          this.uiShowStyleBackupValue = this.getDom().style.display;
          this.getDom().style.display = 'none';
          this.uiIsShow = false;
        }
      },
    };
    utils.inherits(UIBase, EventBase);
  })();
  (function () {
    var utils = baidu.editor.utils,
      UIBase = baidu.editor.ui.UIBase,
      Separator = (baidu.editor.ui.Separator = function (options) {
        this.initOptions(options);
        this.initSeparator();
      });
    Separator.prototype = {
      uiName: 'separator',
      initSeparator: function () {
        this.initUIBase();
      },
      getHtmlTpl: function () {
        return '<div id="##" class="edui-box %%"></div>';
      },
    };
    utils.inherits(Separator, UIBase);
  })();
  (function () {
    var utils = baidu.editor.utils,
      domUtils = baidu.editor.dom.domUtils,
      UIBase = baidu.editor.ui.UIBase,
      uiUtils = baidu.editor.ui.uiUtils;
    var Mask = (baidu.editor.ui.Mask = function (options) {
      this.initOptions(options);
      this.initUIBase();
    });
    Mask.prototype = {
      getHtmlTpl: function () {
        return '<div id="##" class="edui-mask %%" onclick="return $$._onClick(event, this);" onmousedown="return $$._onMouseDown(event, this);"></div>';
      },
      postRender: function () {
        var me = this;
        domUtils.on(window, 'resize', function () {
          setTimeout(function () {
            if (!me.isHidden()) {
              me._fill();
            }
          });
        });
      },
      show: function (zIndex) {
        this._fill();
        this.getDom().style.display = '';
        this.getDom().style.zIndex = zIndex;
      },
      hide: function () {
        this.getDom().style.display = 'none';
        this.getDom().style.zIndex = '';
      },
      isHidden: function () {
        return this.getDom().style.display == 'none';
      },
      _onMouseDown: function () {
        return false;
      },
      _onClick: function (e, target) {
        this.fireEvent('click', e, target);
      },
      _fill: function () {
        var el = this.getDom();
        var vpRect = uiUtils.getViewportRect();
        el.style.width = vpRect.width + 'px';
        el.style.height = vpRect.height + 'px';
      },
    };
    utils.inherits(Mask, UIBase);
  })();
  (function () {
    var utils = baidu.editor.utils,
      uiUtils = baidu.editor.ui.uiUtils,
      domUtils = baidu.editor.dom.domUtils,
      UIBase = baidu.editor.ui.UIBase,
      Popup = (baidu.editor.ui.Popup = function (options) {
        this.initOptions(options);
        this.initPopup();
      });
    var allPopups = [];
    function closeAllPopup(evt, el) {
      for (var i = 0; i < allPopups.length; i++) {
        var pop = allPopups[i];
        if (!pop.isHidden()) {
          if (pop.queryAutoHide(el) !== false) {
            if (evt && /scroll/gi.test(evt.type) && pop.className === 'edui-wordpastepop') return;
            pop.hide();
          }
        }
      }
      if (allPopups.length) pop.editor.fireEvent('afterhidepop');
    }
    Popup.postHide = closeAllPopup;
    var ANCHOR_CLASSES = [
      'edui-anchor-topleft',
      'edui-anchor-topright',
      'edui-anchor-bottomleft',
      'edui-anchor-bottomright',
    ];
    Popup.prototype = {
      SHADOW_RADIUS: 5,
      content: null,
      _hidden: false,
      autoRender: true,
      canSideLeft: true,
      canSideUp: true,
      initPopup: function () {
        this.initUIBase();
        allPopups.push(this);
      },
      getHtmlTpl: function () {
        return (
          '<div id="##" class="edui-popup %%" onmousedown="return false;">' +
          ' <div id="##_body" class="edui-popup-body">' +
          ' <iframe style="position:absolute;z-index:-1;left:0;top:0;background-color: transparent;" frameborder="0" width="100%" height="100%" src="about:blank"></iframe>' +
          ' <div class="edui-shadow"></div>' +
          ' <div id="##_content" class="edui-popup-content">' +
          this.getContentHtmlTpl() +
          '  </div>' +
          ' </div>' +
          '</div>'
        );
      },
      getContentHtmlTpl: function () {
        if (this.content) {
          if (typeof this.content == 'string') {
            return this.content;
          }
          return this.content.renderHtml();
        } else {
          return '';
        }
      },
      _UIBase_postRender: UIBase.prototype.postRender,
      postRender: function () {
        if (this.content instanceof UIBase) {
          this.content.postRender();
        }
        if (this.captureWheel && !this.captured) {
          this.captured = true;
          var winHeight = (document.documentElement.clientHeight || document.body.clientHeight) - 80,
            _height = this.getDom().offsetHeight,
            _top = uiUtils.getClientRect(this.combox.getDom()).top,
            content = this.getDom('content'),
            ifr = this.getDom('body').getElementsByTagName('iframe'),
            me = this;
          ifr.length && (ifr = ifr[0]);
          while (_top + _height > winHeight) {
            _height -= 30;
          }
          content.style.height = _height + 'px';
          ifr && (ifr.style.height = _height + 'px');
          domUtils.on(content, 'onmousewheel' in document.body ? 'mousewheel' : 'DOMMouseScroll', function (e) {
            if (e.preventDefault) {
              e.preventDefault();
            } else {
              e.returnValue = false;
            }
            if (e.wheelDelta) {
              content.scrollTop -= (e.wheelDelta / 120) * 60;
            } else {
              content.scrollTop -= (e.detail / -3) * 60;
            }
          });
        }
        this.fireEvent('postRenderAfter');
        this.hide(true);
        this._UIBase_postRender();
      },
      _doAutoRender: function () {
        if (!this.getDom() && this.autoRender) {
          this.render();
        }
      },
      mesureSize: function () {
        var box = this.getDom('content');
        return uiUtils.getClientRect(box);
      },
      fitSize: function () {
        if (this.captureWheel && this.sized) {
          return this.__size;
        }
        this.sized = true;
        var popBodyEl = this.getDom('body');
        popBodyEl.style.width = '';
        popBodyEl.style.height = '';
        var size = this.mesureSize();
        if (this.captureWheel) {
          popBodyEl.style.width = -(-20 - size.width) + 'px';
          var height = parseInt(this.getDom('content').style.height, 10);
          !window.isNaN(height) && (size.height = height);
        } else {
          popBodyEl.style.width = size.width + 'px';
        }
        popBodyEl.style.height = size.height + 'px';
        this.__size = size;
        this.captureWheel && (this.getDom('content').style.overflow = 'auto');
        return size;
      },
      showAnchor: function (element, hoz) {
        this.showAnchorRect(uiUtils.getClientRect(element), hoz);
      },
      showAnchorRect: function (rect, hoz, adj) {
        this._doAutoRender();
        var vpRect = uiUtils.getViewportRect();
        this.getDom().style.visibility = 'hidden';
        this._show();
        var popSize = this.fitSize();
        var sideLeft, sideUp, left, top;
        if (hoz) {
          sideLeft = this.canSideLeft && rect.right + popSize.width > vpRect.right && rect.left > popSize.width;
          sideUp = this.canSideUp && rect.top + popSize.height > vpRect.bottom && rect.bottom > popSize.height;
          left = sideLeft ? rect.left - popSize.width : rect.right;
          top = sideUp ? rect.bottom - popSize.height : rect.top;
        } else {
          sideLeft = this.canSideLeft && rect.right + popSize.width > vpRect.right && rect.left > popSize.width;
          sideUp = this.canSideUp && rect.top + popSize.height > vpRect.bottom && rect.bottom > popSize.height;
          left = sideLeft ? rect.right - popSize.width : rect.left;
          top = sideUp ? rect.top - popSize.height : rect.bottom;
        }
        if (!sideUp) {
          if (top + popSize.height > vpRect.bottom) {
            top = vpRect.bottom - popSize.height;
          }
        }
        var popEl = this.getDom();
        uiUtils.setViewportOffset(popEl, { left: left, top: top });
        domUtils.removeClasses(popEl, ANCHOR_CLASSES);
        popEl.className += ' ' + ANCHOR_CLASSES[(sideUp ? 1 : 0) * 2 + (sideLeft ? 1 : 0)];
        if (this.editor) {
          popEl.style.zIndex = this.editor.container.style.zIndex * 1 + 10;
          baidu.editor.ui.uiUtils.getFixedLayer().style.zIndex = popEl.style.zIndex - 1;
        }
        this.getDom().style.visibility = 'visible';
      },
      showAt: function (offset) {
        var left = offset.left;
        var top = offset.top;
        var rect = { left: left, top: top, right: left, bottom: top, height: 0, width: 0 };
        this.showAnchorRect(rect, false, true);
      },
      _show: function () {
        if (this._hidden) {
          var box = this.getDom();
          box.style.display = '';
          this._hidden = false;
          this.fireEvent('show');
        }
      },
      isHidden: function () {
        return this._hidden;
      },
      show: function () {
        this._doAutoRender();
        this._show();
      },
      hide: function (notNofity) {
        if (!this._hidden && this.getDom()) {
          this.getDom().style.display = 'none';
          this._hidden = true;
          if (!notNofity) {
            this.fireEvent('hide');
          }
        }
      },
      queryAutoHide: function (el) {
        return !el || !uiUtils.contains(this.getDom(), el);
      },
    };
    utils.inherits(Popup, UIBase);
    domUtils.on(document, 'mousedown', function (evt) {
      var el = evt.target || evt.srcElement;
      closeAllPopup(evt, el);
    });
    domUtils.on(window, 'scroll', function (evt, el) {
      closeAllPopup(evt, el);
    });
  })();
  (function () {
    var utils = baidu.editor.utils,
      UIBase = baidu.editor.ui.UIBase,
      ColorPicker = (baidu.editor.ui.ColorPicker = function (options) {
        this.initOptions(options);
        this.noColorText = this.noColorText || this.editor.getLang('clearColor');
        this.initUIBase();
      });
    ColorPicker.prototype = {
      getHtmlTpl: function () {
        return genColorPicker(this.noColorText, this.editor);
      },
      _onTableClick: function (evt) {
        var tgt = evt.target || evt.srcElement;
        var color = tgt.getAttribute('data-color');
        if (color) {
          this.fireEvent('pickcolor', color);
        }
      },
      _onTableOver: function (evt) {
        var tgt = evt.target || evt.srcElement;
        var color = tgt.getAttribute('data-color');
        if (color) {
          this.getDom('preview').style.backgroundColor = color;
        }
      },
      _onTableOut: function () {
        this.getDom('preview').style.backgroundColor = '';
      },
      _onPickNoColor: function () {
        this.fireEvent('picknocolor');
      },
      _onColorSelect: function (evt) {
        var input = evt.target || evt.srcElement;
        var color = input.value;
        if (color) {
          this.fireEvent('pickcolor', color);
        }
      },
    };
    utils.inherits(ColorPicker, UIBase);
    var COLORS = (
      'ffffff,000000,eeece1,1f497d,4f81bd,c0504d,9bbb59,8064a2,4bacc6,f79646,' +
      'f2f2f2,7f7f7f,ddd9c3,c6d9f0,dbe5f1,f2dcdb,ebf1dd,e5e0ec,dbeef3,fdeada,' +
      'd8d8d8,595959,c4bd97,8db3e2,b8cce4,e5b9b7,d7e3bc,ccc1d9,b7dde8,fbd5b5,' +
      'bfbfbf,3f3f3f,938953,548dd4,95b3d7,d99694,c3d69b,b2a2c7,92cddc,fac08f,' +
      'a5a5a5,262626,494429,17365d,366092,953734,76923c,5f497a,31859b,e36c09,' +
      '7f7f7f,0c0c0c,1d1b10,0f243e,244061,632423,4f6128,3f3151,205867,974806,' +
      'c00000,ff0000,ffc000,ffff00,92d050,00b050,00b0f0,0070c0,002060,7030a0,'
    ).split(',');
    function genColorPicker(noColorText, editor) {
      var html =
        '<div id="##" class="edui-colorpicker %%">' +
        '<div class="edui-colorpicker-topbar edui-clearfix">' +
        '<div id="##_preview" class="edui-colorpicker-preview"><input type="color" id="##_input" onchange="$$._onColorSelect(event,this);" /></div>' +
        '<div unselectable="on" class="edui-colorpicker-nocolor" onclick="$$._onPickNoColor(event, this);">' +
        noColorText +
        '</div>' +
        '</div>' +
        '<table  class="edui-box" style="border-collapse: collapse;" onmouseover="$$._onTableOver(event, this);" onmouseout="$$._onTableOut(event, this);" onclick="return $$._onTableClick(event, this);" cellspacing="0" cellpadding="0">' +
        '<tr style="border-bottom: 1px solid #ddd;font-size: 13px;line-height: 25px;color:#39C;padding-top: 2px"><td colspan="10">' +
        editor.getLang('themeColor') +
        '</td> </tr>' +
        '<tr class="edui-colorpicker-tablefirstrow" >';
      for (var i = 0; i < COLORS.length; i++) {
        if (i && i % 10 === 0) {
          html +=
            '</tr>' +
            (i == 60
              ? '<tr style="border-bottom: 1px solid #ddd;font-size: 13px;line-height: 25px;color:#39C;"><td colspan="10">' +
                editor.getLang('standardColor') +
                '</td></tr>'
              : '') +
            '<tr' +
            (i == 60 ? ' class="edui-colorpicker-tablefirstrow"' : '') +
            '>';
        }
        html +=
          i < 70
            ? '<td style="padding:2px 2px;"><a hidefocus title="' +
              COLORS[i] +
              '" onclick="return false;" href="javascript:" unselectable="on" class="edui-box edui-colorpicker-colorcell"' +
              ' data-color="#' +
              COLORS[i] +
              '"' +
              ' style="background-color:#' +
              COLORS[i] +
              ';border:solid #ccc 1px;' +
              '"' +
              '></a></td>'
            : '';
      }
      html += '</tr>';
      html += '</table></div>';
      return html;
    }
  })();
  (function () {
    var utils = baidu.editor.utils,
      uiUtils = baidu.editor.ui.uiUtils,
      UIBase = baidu.editor.ui.UIBase;
    var TablePicker = (baidu.editor.ui.TablePicker = function (options) {
      this.initOptions(options);
      this.initTablePicker();
    });
    TablePicker.prototype = {
      defaultNumRows: 10,
      defaultNumCols: 10,
      maxNumRows: 20,
      maxNumCols: 20,
      numRows: 10,
      numCols: 10,
      lengthOfCellSide: 22,
      initTablePicker: function () {
        this.initUIBase();
      },
      getHtmlTpl: function () {
        var me = this;
        return (
          '<div id="##" class="edui-tablepicker %%">' +
          '<div class="edui-tablepicker-body">' +
          '<div class="edui-infoarea">' +
          '<span id="##_label" class="edui-label"></span>' +
          '</div>' +
          '<div class="edui-pickarea"' +
          ' onmousemove="$$._onMouseMove(event, this);"' +
          ' onmouseover="$$._onMouseOver(event, this);"' +
          ' onmouseout="$$._onMouseOut(event, this);"' +
          ' onclick="$$._onClick(event, this);"' +
          '>' +
          '<div id="##_overlay" class="edui-overlay"></div>' +
          '</div>' +
          '</div>' +
          '</div>'
        );
      },
      _UIBase_render: UIBase.prototype.render,
      render: function (holder) {
        this._UIBase_render(holder);
        this.getDom('label').innerHTML = '0' + this.editor.getLang('t_row') + ' x 0' + this.editor.getLang('t_col');
      },
      _track: function (numCols, numRows) {
        var style = this.getDom('overlay').style;
        var sideLen = this.lengthOfCellSide;
        style.width = numCols * sideLen + 'px';
        style.height = numRows * sideLen + 'px';
        var label = this.getDom('label');
        label.innerHTML = numCols + this.editor.getLang('t_col') + ' x ' + numRows + this.editor.getLang('t_row');
        this.numCols = numCols;
        this.numRows = numRows;
      },
      _onMouseOver: function (evt, el) {
        var rel = evt.relatedTarget || evt.fromElement;
        if (!uiUtils.contains(el, rel) && el !== rel) {
          this.getDom('label').innerHTML = '0' + this.editor.getLang('t_col') + ' x 0' + this.editor.getLang('t_row');
          this.getDom('overlay').style.visibility = '';
        }
      },
      _onMouseOut: function (evt, el) {
        var rel = evt.relatedTarget || evt.toElement;
        if (!uiUtils.contains(el, rel) && el !== rel) {
          this.getDom('label').innerHTML = '0' + this.editor.getLang('t_col') + ' x 0' + this.editor.getLang('t_row');
          this.getDom('overlay').style.visibility = 'hidden';
        }
      },
      _onMouseMove: function (evt, el) {
        var style = this.getDom('overlay').style;
        var offset = uiUtils.getEventOffset(evt);
        var sideLen = this.lengthOfCellSide;
        var numCols = Math.ceil(offset.left / sideLen);
        var numRows = Math.ceil(offset.top / sideLen);
        this._track(numCols, numRows);
      },
      _onClick: function () {
        this.fireEvent('picktable', this.numCols, this.numRows);
      },
    };
    utils.inherits(TablePicker, UIBase);
  })();
  (function () {
    var browser = baidu.editor.browser,
      domUtils = baidu.editor.dom.domUtils,
      uiUtils = baidu.editor.ui.uiUtils;
    var TPL_STATEFUL =
      'onmousedown="$$.Stateful_onMouseDown(event, this);"' +
      ' onmouseup="$$.Stateful_onMouseUp(event, this);"' +
      (browser.ie
        ? ' onmouseenter="$$.Stateful_onMouseEnter(event, this);"' +
          ' onmouseleave="$$.Stateful_onMouseLeave(event, this);"'
        : ' onmouseover="$$.Stateful_onMouseOver(event, this);"' +
          ' onmouseout="$$.Stateful_onMouseOut(event, this);"');
    baidu.editor.ui.Stateful = {
      alwalysHoverable: false,
      target: null,
      Stateful_init: function () {
        this._Stateful_dGetHtmlTpl = this.getHtmlTpl;
        this.getHtmlTpl = this.Stateful_getHtmlTpl;
      },
      Stateful_getHtmlTpl: function () {
        var tpl = this._Stateful_dGetHtmlTpl();
        return tpl.replace(/stateful/g, function () {
          return TPL_STATEFUL;
        });
      },
      Stateful_onMouseEnter: function (evt, el) {
        this.target = el;
        if (!this.isDisabled() || this.alwalysHoverable) {
          this.addState('hover');
          this.fireEvent('over');
        }
      },
      Stateful_onMouseLeave: function (evt, el) {
        if (!this.isDisabled() || this.alwalysHoverable) {
          this.removeState('hover');
          this.removeState('active');
          this.fireEvent('out');
        }
      },
      Stateful_onMouseOver: function (evt, el) {
        var rel = evt.relatedTarget;
        if (!uiUtils.contains(el, rel) && el !== rel) {
          this.Stateful_onMouseEnter(evt, el);
        }
      },
      Stateful_onMouseOut: function (evt, el) {
        var rel = evt.relatedTarget;
        if (!uiUtils.contains(el, rel) && el !== rel) {
          this.Stateful_onMouseLeave(evt, el);
        }
      },
      Stateful_onMouseDown: function (evt, el) {
        if (!this.isDisabled()) {
          this.addState('active');
        }
      },
      Stateful_onMouseUp: function (evt, el) {
        if (!this.isDisabled()) {
          this.removeState('active');
        }
      },
      Stateful_postRender: function () {
        if (this.disabled && !this.hasState('disabled')) {
          this.addState('disabled');
        }
      },
      hasState: function (state) {
        return domUtils.hasClass(this.getStateDom(), 'edui-state-' + state);
      },
      addState: function (state) {
        if (!this.hasState(state)) {
          this.getStateDom().className += ' edui-state-' + state;
        }
      },
      removeState: function (state) {
        if (this.hasState(state)) {
          domUtils.removeClasses(this.getStateDom(), ['edui-state-' + state]);
        }
      },
      getStateDom: function () {
        return this.getDom('state');
      },
      isChecked: function () {
        return this.hasState('checked');
      },
      setChecked: function (checked) {
        if (!this.isDisabled() && checked) {
          this.addState('checked');
        } else {
          this.removeState('checked');
        }
      },
      isDisabled: function () {
        return this.hasState('disabled');
      },
      setDisabled: function (disabled) {
        if (disabled) {
          this.removeState('hover');
          this.removeState('checked');
          this.removeState('active');
          this.addState('disabled');
        } else {
          this.removeState('disabled');
        }
      },
    };
  })();
  (function () {
    var utils = baidu.editor.utils,
      UIBase = baidu.editor.ui.UIBase,
      Stateful = baidu.editor.ui.Stateful,
      Button = (baidu.editor.ui.Button = function (options) {
        if (options.name) {
          var btnName = options.name;
          var cssRules = options.cssRules;
          if (!options.className) {
            options.className = 'edui-for-' + btnName;
          }
          options.cssRules =
            '.edui-' +
            (options.theme || 'default') +
            ' .edui-toolbar .edui-button.edui-for-' +
            btnName +
            ' .edui-icon {' +
            cssRules +
            '}';
        }
        this.initOptions(options);
        this.initButton();
      });
    Button.prototype = {
      uiName: 'button',
      label: '',
      title: '',
      showIcon: true,
      showText: true,
      cssRules: '',
      initButton: function () {
        this.initUIBase();
        this.Stateful_init();
        if (this.cssRules) {
          utils.cssRule('edui-customize-' + this.name + '-style', this.cssRules);
        }
      },
      getHtmlTpl: function () {
        return (
          '<div id="##" class="edui-box %%">' +
          '<div id="##_state" stateful>' +
          '<div class="%%-wrap"><div id="##_body" unselectable="on" ' +
          (this.title ? 'title="' + this.title + '"' : '') +
          ' class="%%-body" onmousedown="return $$._onMouseDown(event, this);" onclick="return $$._onClick(event, this);">' +
          (this.showIcon ? '<div class="edui-box edui-icon"></div>' : '') +
          (this.showText ? '<div class="edui-box edui-label">' + this.label + '</div>' : '') +
          '</div>' +
          '</div>' +
          '</div></div>'
        );
      },
      postRender: function () {
        this.Stateful_postRender();
        this.setDisabled(this.disabled);
      },
      _onMouseDown: function (e) {
        var target = e.target || e.srcElement,
          tagName = target && target.tagName && target.tagName.toLowerCase();
        if (tagName == 'input' || tagName == 'object' || tagName == 'object') {
          return false;
        }
      },
      _onClick: function () {
        if (!this.isDisabled()) {
          this.fireEvent('click');
        }
      },
      setTitle: function (text) {
        var label = this.getDom('label');
        label.innerHTML = text;
      },
    };
    utils.inherits(Button, UIBase);
    utils.extend(Button.prototype, Stateful);
  })();
  (function () {
    var utils = baidu.editor.utils,
      uiUtils = baidu.editor.ui.uiUtils,
      domUtils = baidu.editor.dom.domUtils,
      UIBase = baidu.editor.ui.UIBase,
      Stateful = baidu.editor.ui.Stateful,
      SplitButton = (baidu.editor.ui.SplitButton = function (options) {
        this.initOptions(options);
        this.initSplitButton();
      });
    SplitButton.prototype = {
      popup: null,
      uiName: 'splitbutton',
      title: '',
      initSplitButton: function () {
        this.initUIBase();
        this.Stateful_init();
        var me = this;
        if (this.popup != null) {
          var popup = this.popup;
          this.popup = null;
          this.setPopup(popup);
        }
      },
      _UIBase_postRender: UIBase.prototype.postRender,
      postRender: function () {
        this.Stateful_postRender();
        this._UIBase_postRender();
      },
      setPopup: function (popup) {
        if (this.popup === popup) return;
        if (this.popup != null) {
          this.popup.dispose();
        }
        popup.addListener('show', utils.bind(this._onPopupShow, this));
        popup.addListener('hide', utils.bind(this._onPopupHide, this));
        popup.addListener(
          'postrender',
          utils.bind(function () {
            popup
              .getDom('body')
              .appendChild(
                uiUtils.createElementByHtml(
                  '<div id="' +
                    this.popup.id +
                    '_bordereraser" class="edui-bordereraser edui-background" style="width:' +
                    (uiUtils.getClientRect(this.getDom()).width + 20) +
                    'px"></div>',
                ),
              );
            popup.getDom().className += ' ' + this.className;
          }, this),
        );
        this.popup = popup;
      },
      _onPopupShow: function () {
        this.addState('opened');
      },
      _onPopupHide: function () {
        this.removeState('opened');
      },
      getHtmlTpl: function () {
        return (
          '<div id="##" class="edui-box %%">' +
          '<div ' +
          (this.title ? 'title="' + this.title + '"' : '') +
          ' id="##_state" stateful><div class="%%-body">' +
          '<div id="##_button_body" class="edui-box edui-button-body" onclick="$$._onButtonClick(event, this);">' +
          '<div class="edui-box edui-icon"></div>' +
          '</div>' +
          '<div class="edui-box edui-splitborder"></div>' +
          '<div class="edui-box edui-arrow" onclick="$$._onArrowClick();"></div>' +
          '</div></div></div>'
        );
      },
      showPopup: function () {
        var rect = uiUtils.getClientRect(this.getDom());
        rect.top -= this.popup.SHADOW_RADIUS;
        rect.height += this.popup.SHADOW_RADIUS;
        this.popup.showAnchorRect(rect);
      },
      _onArrowClick: function (event, el) {
        if (!this.isDisabled()) {
          this.showPopup();
        }
      },
      _onButtonClick: function () {
        if (!this.isDisabled()) {
          this.fireEvent('buttonclick');
        }
      },
    };
    utils.inherits(SplitButton, UIBase);
    utils.extend(SplitButton.prototype, Stateful, true);
  })();
  (function () {
    var utils = baidu.editor.utils,
      uiUtils = baidu.editor.ui.uiUtils,
      ColorPicker = baidu.editor.ui.ColorPicker,
      Popup = baidu.editor.ui.Popup,
      SplitButton = baidu.editor.ui.SplitButton,
      ColorButton = (baidu.editor.ui.ColorButton = function (options) {
        this.initOptions(options);
        this.initColorButton();
      });
    ColorButton.prototype = {
      initColorButton: function () {
        var me = this;
        this.popup = new Popup({
          content: new ColorPicker({
            noColorText: me.editor.getLang('clearColor'),
            editor: me.editor,
            onpickcolor: function (t, color) {
              me._onPickColor(color);
            },
            onpicknocolor: function (t, color) {
              me._onPickNoColor(color);
            },
          }),
          editor: me.editor,
        });
        this.initSplitButton();
      },
      _SplitButton_postRender: SplitButton.prototype.postRender,
      postRender: function () {
        this._SplitButton_postRender();
        this.getDom('button_body').appendChild(
          uiUtils.createElementByHtml('<div id="' + this.id + '_colorlump" class="edui-colorlump"></div>'),
        );
        this.getDom().className += ' edui-colorbutton';
      },
      setColor: function (color) {
        this.getDom('colorlump').style.backgroundColor = color;
        this.color = color;
      },
      _onPickColor: function (color) {
        if (this.fireEvent('pickcolor', color) !== false) {
          this.setColor(color);
          this.popup.hide();
        }
      },
      _onPickNoColor: function (color) {
        if (this.fireEvent('picknocolor') !== false) {
          this.popup.hide();
        }
      },
    };
    utils.inherits(ColorButton, SplitButton);
  })();
  (function () {
    var utils = baidu.editor.utils,
      Popup = baidu.editor.ui.Popup,
      TablePicker = baidu.editor.ui.TablePicker,
      SplitButton = baidu.editor.ui.SplitButton,
      TableButton = (baidu.editor.ui.TableButton = function (options) {
        this.initOptions(options);
        this.initTableButton();
      });
    TableButton.prototype = {
      initTableButton: function () {
        var me = this;
        this.popup = new Popup({
          content: new TablePicker({
            editor: me.editor,
            onpicktable: function (t, numCols, numRows) {
              me._onPickTable(numCols, numRows);
            },
          }),
          editor: me.editor,
        });
        this.initSplitButton();
      },
      _onPickTable: function (numCols, numRows) {
        if (this.fireEvent('picktable', numCols, numRows) !== false) {
          this.popup.hide();
        }
      },
    };
    utils.inherits(TableButton, SplitButton);
  })();
  (function () {
    var utils = baidu.editor.utils,
      UIBase = baidu.editor.ui.UIBase;
    var AutoTypeSetPicker = (baidu.editor.ui.AutoTypeSetPicker = function (options) {
      this.initOptions(options);
      this.initAutoTypeSetPicker();
    });
    AutoTypeSetPicker.prototype = {
      initAutoTypeSetPicker: function () {
        this.initUIBase();
      },
      getHtmlTpl: function () {
        var me = this.editor,
          opt = me.options.autotypeset,
          lang = me.getLang('autoTypeSet');
        var textAlignInputName = 'textAlignValue' + me.uid,
          imageBlockInputName = 'imageBlockLineValue' + me.uid,
          symbolConverInputName = 'symbolConverValue' + me.uid;
        return (
          '<div id="##" class="edui-autotypesetpicker %%">' +
          '<div class="edui-autotypesetpicker-body">' +
          '<table >' +
          '<tr><td nowrap><input type="checkbox" name="mergeEmptyline" ' +
          (opt['mergeEmptyline'] ? 'checked' : '') +
          '>' +
          lang.mergeLine +
          '</td><td colspan="2"><input type="checkbox" name="removeEmptyline" ' +
          (opt['removeEmptyline'] ? 'checked' : '') +
          '>' +
          lang.delLine +
          '</td></tr>' +
          '<tr><td nowrap><input type="checkbox" name="removeClass" ' +
          (opt['removeClass'] ? 'checked' : '') +
          '>' +
          lang.removeFormat +
          '</td><td colspan="2"><input type="checkbox" name="indent" ' +
          (opt['indent'] ? 'checked' : '') +
          '>' +
          lang.indent +
          '</td></tr>' +
          '<tr>' +
          '<td nowrap><input type="checkbox" name="textAlign" ' +
          (opt['textAlign'] ? 'checked' : '') +
          '>' +
          lang.alignment +
          '</td>' +
          '<td colspan="2" id="' +
          textAlignInputName +
          '">' +
          '<input type="radio" name="' +
          textAlignInputName +
          '" value="left" ' +
          (opt['textAlign'] && opt['textAlign'] == 'left' ? 'checked' : '') +
          '>' +
          me.getLang('justifyleft') +
          '<input type="radio" name="' +
          textAlignInputName +
          '" value="center" ' +
          (opt['textAlign'] && opt['textAlign'] == 'center' ? 'checked' : '') +
          '>' +
          me.getLang('justifycenter') +
          '<input type="radio" name="' +
          textAlignInputName +
          '" value="right" ' +
          (opt['textAlign'] && opt['textAlign'] == 'right' ? 'checked' : '') +
          '>' +
          me.getLang('justifyright') +
          '</td>' +
          '</tr>' +
          '<tr>' +
          '<td nowrap><input type="checkbox" name="imageBlockLine" ' +
          (opt['imageBlockLine'] ? 'checked' : '') +
          '>' +
          lang.imageFloat +
          '</td>' +
          '<td nowrap id="' +
          imageBlockInputName +
          '">' +
          '<input type="radio" name="' +
          imageBlockInputName +
          '" value="none" ' +
          (opt['imageBlockLine'] && opt['imageBlockLine'] == 'none' ? 'checked' : '') +
          '>' +
          me.getLang('default') +
          '<input type="radio" name="' +
          imageBlockInputName +
          '" value="left" ' +
          (opt['imageBlockLine'] && opt['imageBlockLine'] == 'left' ? 'checked' : '') +
          '>' +
          me.getLang('justifyleft') +
          '<input type="radio" name="' +
          imageBlockInputName +
          '" value="center" ' +
          (opt['imageBlockLine'] && opt['imageBlockLine'] == 'center' ? 'checked' : '') +
          '>' +
          me.getLang('justifycenter') +
          '<input type="radio" name="' +
          imageBlockInputName +
          '" value="right" ' +
          (opt['imageBlockLine'] && opt['imageBlockLine'] == 'right' ? 'checked' : '') +
          '>' +
          me.getLang('justifyright') +
          '</td>' +
          '</tr>' +
          '<tr><td nowrap><input type="checkbox" name="clearFontSize" ' +
          (opt['clearFontSize'] ? 'checked' : '') +
          '>' +
          lang.removeFontsize +
          '</td><td colspan="2"><input type="checkbox" name="clearFontFamily" ' +
          (opt['clearFontFamily'] ? 'checked' : '') +
          '>' +
          lang.removeFontFamily +
          '</td></tr>' +
          '<tr><td nowrap colspan="3"><input type="checkbox" name="removeEmptyNode" ' +
          (opt['removeEmptyNode'] ? 'checked' : '') +
          '>' +
          lang.removeHtml +
          '</td></tr>' +
          '<tr><td nowrap colspan="3"><input type="checkbox" name="pasteFilter" ' +
          (opt['pasteFilter'] ? 'checked' : '') +
          '>' +
          lang.pasteFilter +
          '</td></tr>' +
          '<tr>' +
          '<td nowrap><input type="checkbox" name="symbolConver" ' +
          (opt['bdc2sb'] || opt['tobdc'] ? 'checked' : '') +
          '>' +
          lang.symbol +
          '</td>' +
          '<td id="' +
          symbolConverInputName +
          '">' +
          '<input type="radio" name="bdc" value="bdc2sb" ' +
          (opt['bdc2sb'] ? 'checked' : '') +
          '>' +
          lang.bdc2sb +
          '<input type="radio" name="bdc" value="tobdc" ' +
          (opt['tobdc'] ? 'checked' : '') +
          '>' +
          lang.tobdc +
          '' +
          '</td>' +
          '<td nowrap align="right"><button >' +
          lang.run +
          '</button></td>' +
          '</tr>' +
          '</table>' +
          '</div>' +
          '</div>'
        );
      },
      _UIBase_render: UIBase.prototype.render,
    };
    utils.inherits(AutoTypeSetPicker, UIBase);
  })();
  (function () {
    var utils = baidu.editor.utils,
      Popup = baidu.editor.ui.Popup,
      AutoTypeSetPicker = baidu.editor.ui.AutoTypeSetPicker,
      SplitButton = baidu.editor.ui.SplitButton,
      AutoTypeSetButton = (baidu.editor.ui.AutoTypeSetButton = function (options) {
        this.initOptions(options);
        this.initAutoTypeSetButton();
      });
    function getPara(me) {
      var opt = {},
        cont = me.getDom(),
        editorId = me.editor.uid,
        inputType = null,
        attrName = null,
        ipts = domUtils.getElementsByTagName(cont, 'input');
      for (var i = ipts.length - 1, ipt; (ipt = ipts[i--]); ) {
        inputType = ipt.getAttribute('type');
        if (inputType == 'checkbox') {
          attrName = ipt.getAttribute('name');
          opt[attrName] && delete opt[attrName];
          if (ipt.checked) {
            var attrValue = document.getElementById(attrName + 'Value' + editorId);
            if (attrValue) {
              if (/input/gi.test(attrValue.tagName)) {
                opt[attrName] = attrValue.value;
              } else {
                var iptChilds = attrValue.getElementsByTagName('input');
                for (var j = iptChilds.length - 1, iptchild; (iptchild = iptChilds[j--]); ) {
                  if (iptchild.checked) {
                    opt[attrName] = iptchild.value;
                    break;
                  }
                }
              }
            } else {
              opt[attrName] = true;
            }
          } else {
            opt[attrName] = false;
          }
        } else {
          opt[ipt.getAttribute('value')] = ipt.checked;
        }
      }
      var selects = domUtils.getElementsByTagName(cont, 'select');
      for (var i = 0, si; (si = selects[i++]); ) {
        var attr = si.getAttribute('name');
        opt[attr] = opt[attr] ? si.value : '';
      }
      utils.extend(me.editor.options.autotypeset, opt);
      me.editor.setPreferences('autotypeset', opt);
    }
    AutoTypeSetButton.prototype = {
      initAutoTypeSetButton: function () {
        var me = this;
        this.popup = new Popup({
          content: new AutoTypeSetPicker({ editor: me.editor }),
          editor: me.editor,
          hide: function () {
            if (!this._hidden && this.getDom()) {
              getPara(this);
              this.getDom().style.display = 'none';
              this._hidden = true;
              this.fireEvent('hide');
            }
          },
        });
        var flag = 0;
        this.popup.addListener('postRenderAfter', function () {
          var popupUI = this;
          if (flag) return;
          var cont = this.getDom(),
            btn = cont.getElementsByTagName('button')[0];
          btn.onclick = function () {
            getPara(popupUI);
            me.editor.execCommand('autotypeset');
            popupUI.hide();
          };
          domUtils.on(cont, 'click', function (e) {
            var target = e.target || e.srcElement,
              editorId = me.editor.uid;
            if (target && target.tagName == 'INPUT') {
              if (target.name == 'imageBlockLine' || target.name == 'textAlign' || target.name == 'symbolConver') {
                var checked = target.checked,
                  radioTd = document.getElementById(target.name + 'Value' + editorId),
                  radios = radioTd.getElementsByTagName('input'),
                  defalutSelect = { imageBlockLine: 'none', textAlign: 'left', symbolConver: 'tobdc' };
                for (var i = 0; i < radios.length; i++) {
                  if (checked) {
                    if (radios[i].value == defalutSelect[target.name]) {
                      radios[i].checked = 'checked';
                    }
                  } else {
                    radios[i].checked = false;
                  }
                }
              }
              if (
                target.name == 'imageBlockLineValue' + editorId ||
                target.name == 'textAlignValue' + editorId ||
                target.name == 'bdc'
              ) {
                var checkboxs = target.parentNode.previousSibling.getElementsByTagName('input');
                checkboxs && (checkboxs[0].checked = true);
              }
              getPara(popupUI);
            }
          });
          flag = 1;
        });
        this.initSplitButton();
      },
    };
    utils.inherits(AutoTypeSetButton, SplitButton);
  })();
  (function () {
    var utils = baidu.editor.utils,
      Popup = baidu.editor.ui.Popup,
      Stateful = baidu.editor.ui.Stateful,
      UIBase = baidu.editor.ui.UIBase;
    var CellAlignPicker = (baidu.editor.ui.CellAlignPicker = function (options) {
      this.initOptions(options);
      this.initSelected();
      this.initCellAlignPicker();
    });
    CellAlignPicker.prototype = {
      initSelected: function () {
        var status = { valign: { top: 0, middle: 1, bottom: 2 }, align: { left: 0, center: 1, right: 2 }, count: 3 },
          result = -1;
        if (this.selected) {
          this.selectedIndex = status.valign[this.selected.valign] * status.count + status.align[this.selected.align];
        }
      },
      initCellAlignPicker: function () {
        this.initUIBase();
        this.Stateful_init();
      },
      getHtmlTpl: function () {
        var alignType = ['left', 'center', 'right'],
          COUNT = 9,
          tempClassName = null,
          tempIndex = -1,
          tmpl = [];
        for (var i = 0; i < COUNT; i++) {
          tempClassName = this.selectedIndex === i ? ' class="edui-cellalign-selected" ' : '';
          tempIndex = i % 3;
          tempIndex === 0 && tmpl.push('<tr>');
          tmpl.push(
            '<td index="' +
              i +
              '" ' +
              tempClassName +
              ' stateful><div class="edui-icon edui-' +
              alignType[tempIndex] +
              '"></div></td>',
          );
          tempIndex === 2 && tmpl.push('</tr>');
        }
        return (
          '<div id="##" class="edui-cellalignpicker %%">' +
          '<div class="edui-cellalignpicker-body">' +
          '<table onclick="$$._onClick(event);">' +
          tmpl.join('') +
          '</table>' +
          '</div>' +
          '</div>'
        );
      },
      getStateDom: function () {
        return this.target;
      },
      _onClick: function (evt) {
        var target = evt.target || evt.srcElement;
        if (/icon/.test(target.className)) {
          this.items[target.parentNode.getAttribute('index')].onclick();
          Popup.postHide(evt);
        }
      },
      _UIBase_render: UIBase.prototype.render,
    };
    utils.inherits(CellAlignPicker, UIBase);
    utils.extend(CellAlignPicker.prototype, Stateful, true);
  })();
  (function () {
    var utils = baidu.editor.utils,
      Stateful = baidu.editor.ui.Stateful,
      uiUtils = baidu.editor.ui.uiUtils,
      UIBase = baidu.editor.ui.UIBase;
    var PastePicker = (baidu.editor.ui.PastePicker = function (options) {
      this.initOptions(options);
      this.initPastePicker();
    });
    PastePicker.prototype = {
      initPastePicker: function () {
        this.initUIBase();
        this.Stateful_init();
      },
      getHtmlTpl: function () {
        return (
          '<div class="edui-pasteicon" onclick="$$._onClick(this)"></div>' +
          '<div class="edui-pastecontainer">' +
          '<div class="edui-title">' +
          this.editor.getLang('pasteOpt') +
          '</div>' +
          '<div class="edui-button">' +
          '<div title="' +
          this.editor.getLang('pasteSourceFormat') +
          '" onclick="$$.format(false)" stateful>' +
          '<div class="edui-richtxticon"></div></div>' +
          '<div title="' +
          this.editor.getLang('tagFormat') +
          '" onclick="$$.format(2)" stateful>' +
          '<div class="edui-tagicon"></div></div>' +
          '<div title="' +
          this.editor.getLang('pasteTextFormat') +
          '" onclick="$$.format(true)" stateful>' +
          '<div class="edui-plaintxticon"></div></div>' +
          '</div>' +
          '</div>' +
          '</div>'
        );
      },
      getStateDom: function () {
        return this.target;
      },
      format: function (param) {
        this.editor.ui._isTransfer = true;
        this.editor.fireEvent('pasteTransfer', param);
      },
      _onClick: function (cur) {
        var node = domUtils.getNextDomNode(cur),
          screenHt = uiUtils.getViewportRect().height,
          subPop = uiUtils.getClientRect(node);
        if (subPop.top + subPop.height > screenHt) node.style.top = -subPop.height - cur.offsetHeight + 'px';
        else node.style.top = '';
        if (/hidden/gi.test(domUtils.getComputedStyle(node, 'visibility'))) {
          node.style.visibility = 'visible';
          domUtils.addClass(cur, 'edui-state-opened');
        } else {
          node.style.visibility = 'hidden';
          domUtils.removeClasses(cur, 'edui-state-opened');
        }
      },
      _UIBase_render: UIBase.prototype.render,
    };
    utils.inherits(PastePicker, UIBase);
    utils.extend(PastePicker.prototype, Stateful, true);
  })();
  (function () {
    var utils = baidu.editor.utils,
      uiUtils = baidu.editor.ui.uiUtils,
      UIBase = baidu.editor.ui.UIBase,
      Toolbar = (baidu.editor.ui.Toolbar = function (options) {
        this.initOptions(options);
        this.initToolbar();
      });
    Toolbar.prototype = {
      items: null,
      initToolbar: function () {
        this.items = this.items || [];
        this.initUIBase();
      },
      add: function (item, index) {
        if (index === undefined) {
          this.items.push(item);
        } else {
          this.items.splice(index, 0, item);
        }
      },
      getHtmlTpl: function () {
        var buff = [];
        for (var i = 0; i < this.items.length; i++) {
          buff[i] = this.items[i].renderHtml();
        }
        return (
          '<div id="##" class="edui-toolbar %%" onselectstart="return false;" onmousedown="return $$._onMouseDown(event, this);">' +
          buff.join('') +
          '</div>'
        );
      },
      postRender: function () {
        var box = this.getDom();
        for (var i = 0; i < this.items.length; i++) {
          this.items[i].postRender();
        }
        uiUtils.makeUnselectable(box);
      },
      _onMouseDown: function (e) {
        var target = e.target || e.srcElement,
          tagName = target && target.tagName && target.tagName.toLowerCase();
        if (tagName == 'input' || tagName == 'object' || tagName == 'object') {
          return false;
        }
      },
    };
    utils.inherits(Toolbar, UIBase);
  })();
  (function () {
    var utils = baidu.editor.utils,
      domUtils = baidu.editor.dom.domUtils,
      uiUtils = baidu.editor.ui.uiUtils,
      UIBase = baidu.editor.ui.UIBase,
      Popup = baidu.editor.ui.Popup,
      Stateful = baidu.editor.ui.Stateful,
      CellAlignPicker = baidu.editor.ui.CellAlignPicker,
      QuickOperate = (baidu.editor.ui.QuickOperate = function (options) {
        this.initOptions(options);
      });
    QuickOperate.prototype = {
      uiName: 'quick-operate',
      _Popup_getContentHtmlTpl: Popup.prototype.getContentHtmlTpl,
      getContentHtmlTpl: function () {
        return [
          '<div class="edui-quick-operate">',
          ' <div class="edui-quick-operate-status">',
          '   <div class="edui-quick-operate-icon"><i class="icon icon-image"></i></div>',
          '   <div class="edui-quick-operate-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" data-icon="DragOutlined"><path d="M8.25 6.5a1.75 1.75 0 1 0 0-3.5 1.75 1.75 0 0 0 0 3.5Zm0 7.25a1.75 1.75 0 1 0 0-3.5 1.75 1.75 0 0 0 0 3.5Zm1.75 5.5a1.75 1.75 0 1 1-3.5 0 1.75 1.75 0 0 1 3.5 0ZM14.753 6.5a1.75 1.75 0 1 0 0-3.5 1.75 1.75 0 0 0 0 3.5ZM16.5 12a1.75 1.75 0 1 1-3.5 0 1.75 1.75 0 0 1 3.5 0Zm-1.747 9a1.75 1.75 0 1 0 0-3.5 1.75 1.75 0 0 0 0 3.5Z" fill="currentColor"></path></svg></div>',
          ' </div>',
          ' <div class="edui-quick-operate-menu">',
          '   <div class="item"><i class="icon icon-image"></i> 删除</div>',
          '   <div class="item"><i class="icon icon-image"></i> 左对齐</div>',
          '   <div class="item"><i class="icon icon-image"></i> 右对齐</div>',
          ' </div>',
          '</div>',
        ].join('');
      },
      destroy: function () {
        if (this.getDom()) {
          domUtils.remove(this.getDom());
        }
      },
      dispose: function () {
        this.destroy();
      },
    };
    utils.inherits(QuickOperate, Popup);
  })();
  (function () {
    var utils = baidu.editor.utils,
      domUtils = baidu.editor.dom.domUtils,
      uiUtils = baidu.editor.ui.uiUtils,
      UIBase = baidu.editor.ui.UIBase,
      Popup = baidu.editor.ui.Popup,
      Stateful = baidu.editor.ui.Stateful,
      CellAlignPicker = baidu.editor.ui.CellAlignPicker,
      Menu = (baidu.editor.ui.Menu = function (options) {
        this.initOptions(options);
        this.initMenu();
      });
    var menuSeparator = {
      renderHtml: function () {
        return '<div class="edui-menuitem edui-menuseparator"><div class="edui-menuseparator-inner"></div></div>';
      },
      postRender: function () {},
      queryAutoHide: function () {
        return true;
      },
    };
    Menu.prototype = {
      items: null,
      uiName: 'menu',
      initMenu: function () {
        this.items = this.items || [];
        this.initPopup();
        this.initItems();
      },
      initItems: function () {
        for (var i = 0; i < this.items.length; i++) {
          var item = this.items[i];
          if (item == '-') {
            this.items[i] = this.getSeparator();
          } else if (!(item instanceof MenuItem)) {
            item.editor = this.editor;
            item.theme = this.editor.options.theme;
            this.items[i] = this.createItem(item);
          }
        }
      },
      getSeparator: function () {
        return menuSeparator;
      },
      createItem: function (item) {
        item.menu = this;
        return new MenuItem(item);
      },
      _Popup_getContentHtmlTpl: Popup.prototype.getContentHtmlTpl,
      getContentHtmlTpl: function () {
        if (this.items.length == 0) {
          return this._Popup_getContentHtmlTpl();
        }
        var buff = [];
        for (var i = 0; i < this.items.length; i++) {
          var item = this.items[i];
          buff[i] = item.renderHtml();
        }
        return '<div class="%%-body">' + buff.join('') + '</div>';
      },
      _Popup_postRender: Popup.prototype.postRender,
      postRender: function () {
        var me = this;
        for (var i = 0; i < this.items.length; i++) {
          var item = this.items[i];
          item.ownerMenu = this;
          item.postRender();
        }
        domUtils.on(this.getDom(), 'mouseover', function (evt) {
          evt = evt || event;
          var rel = evt.relatedTarget || evt.fromElement;
          var el = me.getDom();
          if (!uiUtils.contains(el, rel) && el !== rel) {
            me.fireEvent('over');
          }
        });
        this._Popup_postRender();
      },
      queryAutoHide: function (el) {
        if (el) {
          if (uiUtils.contains(this.getDom(), el)) {
            return false;
          }
          for (var i = 0; i < this.items.length; i++) {
            var item = this.items[i];
            if (item.queryAutoHide(el) === false) {
              return false;
            }
          }
        }
      },
      clearItems: function () {
        for (var i = 0; i < this.items.length; i++) {
          var item = this.items[i];
          clearTimeout(item._showingTimer);
          clearTimeout(item._closingTimer);
          if (item.subMenu) {
            item.subMenu.destroy();
          }
        }
        this.items = [];
      },
      destroy: function () {
        if (this.getDom()) {
          domUtils.remove(this.getDom());
        }
        this.clearItems();
      },
      dispose: function () {
        this.destroy();
      },
    };
    utils.inherits(Menu, Popup);
    var MenuItem = (baidu.editor.ui.MenuItem = function (options) {
      this.initOptions(options);
      this.initUIBase();
      this.Stateful_init();
      if (this.subMenu && !(this.subMenu instanceof Menu)) {
        if (options.className && options.className.indexOf('aligntd') != -1) {
          var me = this;
          this.subMenu.selected = this.editor.queryCommandValue('cellalignment');
          this.subMenu = new Popup({
            content: new CellAlignPicker(this.subMenu),
            parentMenu: me,
            editor: me.editor,
            destroy: function () {
              if (this.getDom()) {
                domUtils.remove(this.getDom());
              }
            },
          });
          this.subMenu.addListener('postRenderAfter', function () {
            domUtils.on(this.getDom(), 'mouseover', function () {
              me.addState('opened');
            });
          });
        } else {
          this.subMenu = new Menu(this.subMenu);
        }
      }
    });
    MenuItem.prototype = {
      label: '',
      subMenu: null,
      ownerMenu: null,
      uiName: 'menuitem',
      alwalysHoverable: true,
      getHtmlTpl: function () {
        return (
          '<div id="##" class="%%" stateful onclick="$$._onClick(event, this);">' +
          '<div class="%%-body">' +
          this.renderLabelHtml() +
          '</div>' +
          '</div>'
        );
      },
      postRender: function () {
        var me = this;
        this.addListener('over', function () {
          me.ownerMenu.fireEvent('submenuover', me);
          if (me.subMenu) {
            me.delayShowSubMenu();
          }
        });
        if (this.subMenu) {
          this.getDom().className += ' edui-hassubmenu';
          this.subMenu.render();
          this.addListener('out', function () {
            me.delayHideSubMenu();
          });
          this.subMenu.addListener('over', function () {
            clearTimeout(me._closingTimer);
            me._closingTimer = null;
            me.addState('opened');
          });
          this.ownerMenu.addListener('hide', function () {
            me.hideSubMenu();
          });
          this.ownerMenu.addListener('submenuover', function (t, subMenu) {
            if (subMenu !== me) {
              me.delayHideSubMenu();
            }
          });
          this.subMenu._bakQueryAutoHide = this.subMenu.queryAutoHide;
          this.subMenu.queryAutoHide = function (el) {
            if (el && uiUtils.contains(me.getDom(), el)) {
              return false;
            }
            return this._bakQueryAutoHide(el);
          };
        }
        this.getDom().style.tabIndex = '-1';
        uiUtils.makeUnselectable(this.getDom());
        this.Stateful_postRender();
      },
      delayShowSubMenu: function () {
        var me = this;
        if (!me.isDisabled()) {
          me.addState('opened');
          clearTimeout(me._showingTimer);
          clearTimeout(me._closingTimer);
          me._closingTimer = null;
          me._showingTimer = setTimeout(function () {
            me.showSubMenu();
          }, 250);
        }
      },
      delayHideSubMenu: function () {
        var me = this;
        if (!me.isDisabled()) {
          me.removeState('opened');
          clearTimeout(me._showingTimer);
          if (!me._closingTimer) {
            me._closingTimer = setTimeout(function () {
              if (!me.hasState('opened')) {
                me.hideSubMenu();
              }
              me._closingTimer = null;
            }, 400);
          }
        }
      },
      renderLabelHtml: function () {
        return (
          '<div class="edui-arrow"></div>' +
          '<div class="edui-box edui-icon"></div>' +
          '<div class="edui-box edui-label %%-label">' +
          (this.label || '') +
          '</div>'
        );
      },
      getStateDom: function () {
        return this.getDom();
      },
      queryAutoHide: function (el) {
        if (this.subMenu && this.hasState('opened')) {
          return this.subMenu.queryAutoHide(el);
        }
      },
      _onClick: function (event, this_) {
        if (this.hasState('disabled')) return;
        if (this.fireEvent('click', event, this_) !== false) {
          if (this.subMenu) {
            this.showSubMenu();
          } else {
            Popup.postHide(event);
          }
        }
      },
      showSubMenu: function () {
        var rect = uiUtils.getClientRect(this.getDom());
        rect.right -= 5;
        rect.left += 2;
        rect.width -= 7;
        rect.top -= 4;
        rect.bottom += 4;
        rect.height += 8;
        this.subMenu.showAnchorRect(rect, true, true);
      },
      hideSubMenu: function () {
        this.subMenu.hide();
      },
    };
    utils.inherits(MenuItem, UIBase);
    utils.extend(MenuItem.prototype, Stateful, true);
  })();
  (function () {
    var utils = baidu.editor.utils,
      uiUtils = baidu.editor.ui.uiUtils,
      Menu = baidu.editor.ui.Menu,
      SplitButton = baidu.editor.ui.SplitButton,
      Combox = (baidu.editor.ui.Combox = function (options) {
        this.initOptions(options);
        this.initCombox();
      });
    Combox.prototype = {
      uiName: 'combox',
      onbuttonclick: function () {
        this.showPopup();
      },
      initCombox: function () {
        var me = this;
        this.items = this.items || [];
        for (var i = 0; i < this.items.length; i++) {
          var item = this.items[i];
          item.uiName = 'listitem';
          item.index = i;
          item.onclick = function () {
            me.selectByIndex(this.index);
          };
        }
        this.popup = new Menu({
          items: this.items,
          uiName: 'list',
          editor: this.editor,
          captureWheel: true,
          combox: this,
        });
        this.initSplitButton();
      },
      _SplitButton_postRender: SplitButton.prototype.postRender,
      postRender: function () {
        this._SplitButton_postRender();
        this.setLabel(this.label || '');
        this.setValue(this.initValue || '');
      },
      showPopup: function () {
        var rect = uiUtils.getClientRect(this.getDom());
        rect.top += 1;
        rect.bottom -= 1;
        rect.height -= 2;
        this.popup.showAnchorRect(rect);
      },
      getValue: function () {
        return this.value;
      },
      setValue: function (value) {
        var index = this.indexByValue(value);
        if (index != -1) {
          this.selectedIndex = index;
          this.setLabel(this.items[index].label);
          this.value = this.items[index].value;
        } else {
          this.selectedIndex = -1;
          this.setLabel(this.getLabelForUnknowValue(value));
          this.value = value;
        }
      },
      setLabel: function (label) {
        this.getDom('button_body').innerHTML = label;
        this.label = label;
      },
      getLabelForUnknowValue: function (value) {
        return value;
      },
      indexByValue: function (value) {
        for (var i = 0; i < this.items.length; i++) {
          if (value == this.items[i].value) {
            return i;
          }
        }
        return -1;
      },
      getItem: function (index) {
        return this.items[index];
      },
      selectByIndex: function (index) {
        if (index < this.items.length && this.fireEvent('select', index) !== false) {
          this.selectedIndex = index;
          this.value = this.items[index].value;
          this.setLabel(this.items[index].label);
        }
      },
    };
    utils.inherits(Combox, SplitButton);
  })();
  (function () {
    var utils = baidu.editor.utils,
      domUtils = baidu.editor.dom.domUtils,
      uiUtils = baidu.editor.ui.uiUtils,
      Mask = baidu.editor.ui.Mask,
      UIBase = baidu.editor.ui.UIBase,
      Button = baidu.editor.ui.Button,
      Dialog = (baidu.editor.ui.Dialog = function (options) {
        if (options.name) {
          var name = options.name;
          var cssRules = options.cssRules;
          if (!options.className) {
            options.className = 'edui-for-' + name;
          }
          if (cssRules) {
            options.cssRules = '.edui-for-' + name + ' .edui-dialog-content  {' + cssRules + '}';
          }
        }
        this.initOptions(
          utils.extend(
            {
              autoReset: true,
              draggable: true,
              onok: function () {},
              oncancel: function () {},
              onclose: function (t, ok) {
                return ok ? this.onok() : this.oncancel();
              },
              holdScroll: false,
            },
            options,
          ),
        );
        this.initDialog();
      });
    var modalMask;
    var dragMask;
    var activeDialog;
    Dialog.prototype = {
      draggable: false,
      uiName: 'dialog',
      initDialog: function () {
        var me = this,
          theme = this.editor.options.theme;
        if (this.cssRules) {
          this.cssRules = '.edui-' + theme + ' ' + this.cssRules;
          utils.cssRule('edui-customize-' + this.name + '-style', this.cssRules);
        }
        this.initUIBase();
        this.modalMask =
          modalMask ||
          (modalMask = new Mask({
            className: 'edui-dialog-modalmask',
            theme: theme,
            onclick: function () {
              activeDialog && activeDialog.close(false);
            },
          }));
        this.dragMask = dragMask || (dragMask = new Mask({ className: 'edui-dialog-dragmask', theme: theme }));
        this.closeButton = new Button({
          className: 'edui-dialog-closebutton',
          title: me.closeDialog,
          theme: theme,
          onclick: function () {
            me.close(false);
          },
        });
        this.fullscreen && this.initResizeEvent();
        if (this.buttons) {
          for (var i = 0; i < this.buttons.length; i++) {
            if (!(this.buttons[i] instanceof Button)) {
              this.buttons[i] = new Button(utils.extend(this.buttons[i], { editor: this.editor }, true));
            }
          }
        }
      },
      initResizeEvent: function () {
        var me = this;
        domUtils.on(window, 'resize', function () {
          if (me._hidden || me._hidden === undefined) {
            return;
          }
          if (me.__resizeTimer) {
            window.clearTimeout(me.__resizeTimer);
          }
          me.__resizeTimer = window.setTimeout(function () {
            me.__resizeTimer = null;
            var dialogWrapNode = me.getDom(),
              contentNode = me.getDom('content'),
              wrapRect = UE.ui.uiUtils.getClientRect(dialogWrapNode),
              contentRect = UE.ui.uiUtils.getClientRect(contentNode),
              vpRect = uiUtils.getViewportRect();
            contentNode.style.width = vpRect.width - wrapRect.width + contentRect.width + 'px';
            contentNode.style.height = vpRect.height - wrapRect.height + contentRect.height + 'px';
            dialogWrapNode.style.width = vpRect.width + 'px';
            dialogWrapNode.style.height = vpRect.height + 'px';
            me.fireEvent('resize');
          }, 100);
        });
      },
      fitSize: function () {
        var popBodyEl = this.getDom('body');
        var $foot = popBodyEl.querySelector('.edui-dialog-foot');
        var headHeight = 30;
        var footHeight = 50;
        var heightWithoutBody = headHeight + footHeight;
        if (!$foot) {
          heightWithoutBody -= footHeight;
        }
        var size = this.mesureSize();
        var winSize = uiUtils.getViewportRect();
        var width = size.width;
        var height = size.height - heightWithoutBody;
        var maxWidth = winSize.width - 2;
        var maxHeight = winSize.height - heightWithoutBody - 2;
        if (width > maxWidth) {
          height = (height * maxWidth) / width;
          width = maxWidth;
        }
        if (height > maxHeight) {
          width = (width * maxHeight) / height;
          height = maxHeight;
        }
        var scale = width / size.width;
        var $content = popBodyEl.querySelector('.edui-dialog-content');
        if (!$content.dataset.dialogScaled) {
          $content.dataset.dialogScaled = true;
          $content.style.width = width + 'px';
          $content.style.height = height + 'px';
          var $iframe = popBodyEl.querySelector('.edui-dialog-content iframe');
          $iframe.style.width = size.width + 'px';
          $iframe.style.height = size.height - heightWithoutBody + 'px';
          $iframe.style.transformOrigin = '0 0';
          $iframe.style.transform = 'scale(' + scale + ')';
          size.width = width;
          size.height = height + heightWithoutBody;
        }
        popBodyEl.style.width = size.width + 'px';
        popBodyEl.style.height = size.height + 'px';
        return size;
      },
      safeSetOffset: function (offset) {
        var me = this;
        var el = me.getDom();
        var vpRect = uiUtils.getViewportRect();
        var rect = uiUtils.getClientRect(el);
        var left = offset.left;
        if (left + rect.width > vpRect.right) {
          left = vpRect.right - rect.width;
        }
        var top = offset.top;
        if (top + rect.height > vpRect.bottom) {
          top = vpRect.bottom - rect.height;
        }
        el.style.left = Math.max(left, 0) + 'px';
        el.style.top = Math.max(top, 0) + 'px';
      },
      showAtCenter: function () {
        var vpRect = uiUtils.getViewportRect();
        if (!this.fullscreen) {
          this.getDom().style.display = '';
          var popSize = this.fitSize();
          var titleHeight = this.getDom('titlebar').offsetHeight | 0;
          var left = vpRect.width / 2 - popSize.width / 2;
          var top = vpRect.height / 2 - (popSize.height - titleHeight) / 2 - titleHeight;
          var popEl = this.getDom();
          this.safeSetOffset({ left: Math.max(left | 0, 0), top: Math.max(top | 0, 0) });
          if (!domUtils.hasClass(popEl, 'edui-state-centered')) {
            popEl.className += ' edui-state-centered';
          }
        } else {
          var dialogWrapNode = this.getDom(),
            contentNode = this.getDom('content');
          dialogWrapNode.style.display = 'block';
          var wrapRect = UE.ui.uiUtils.getClientRect(dialogWrapNode),
            contentRect = UE.ui.uiUtils.getClientRect(contentNode);
          dialogWrapNode.style.left = '-100000px';
          contentNode.style.width = vpRect.width - wrapRect.width + contentRect.width + 'px';
          contentNode.style.height = vpRect.height - wrapRect.height + contentRect.height + 'px';
          dialogWrapNode.style.width = vpRect.width + 'px';
          dialogWrapNode.style.height = vpRect.height + 'px';
          dialogWrapNode.style.left = 0;
          this._originalContext = {
            html: {
              overflowX: document.documentElement.style.overflowX,
              overflowY: document.documentElement.style.overflowY,
            },
            body: { overflowX: document.body.style.overflowX, overflowY: document.body.style.overflowY },
          };
          document.documentElement.style.overflowX = 'hidden';
          document.documentElement.style.overflowY = 'hidden';
          document.body.style.overflowX = 'hidden';
          document.body.style.overflowY = 'hidden';
        }
        this._show();
      },
      getContentHtml: function () {
        var contentHtml = '';
        if (typeof this.content == 'string') {
          contentHtml = this.content;
        } else if (this.iframeUrl) {
          contentHtml =
            '<span id="' +
            this.id +
            '_contmask" class="dialogcontmask"></span><iframe id="' +
            this.id +
            '_iframe" class="%%-iframe" height="100%" width="100%" frameborder="0" src="' +
            this.iframeUrl +
            '"></iframe>';
        }
        return contentHtml;
      },
      getHtmlTpl: function () {
        var footHtml = '';
        if (this.buttons) {
          var buff = [];
          for (var i = 0; i < this.buttons.length; i++) {
            buff[i] = this.buttons[i].renderHtml();
          }
          footHtml =
            '<div class="%%-foot">' + '<div id="##_buttons" class="%%-buttons">' + buff.join('') + '</div>' + '</div>';
        }
        return (
          '<div id="##" class="%%"><div ' +
          (!this.fullscreen ? 'class="%%"' : 'class="%%-wrap edui-dialog-fullscreen-flag"') +
          '><div id="##_body" class="%%-body">' +
          '<div class="%%-shadow"></div>' +
          '<div id="##_titlebar" class="%%-titlebar">' +
          '<div class="%%-draghandle" onmousedown="$$._onTitlebarMouseDown(event, this);">' +
          '<span class="%%-caption">' +
          (this.title || '') +
          '</span>' +
          '</div>' +
          this.closeButton.renderHtml() +
          '</div>' +
          '<div id="##_content" class="%%-content">' +
          (this.autoReset ? '' : this.getContentHtml()) +
          '</div>' +
          footHtml +
          '</div></div></div>'
        );
      },
      postRender: function () {
        if (!this.modalMask.getDom()) {
          this.modalMask.render();
          this.modalMask.hide();
        }
        if (!this.dragMask.getDom()) {
          this.dragMask.render();
          this.dragMask.hide();
        }
        var me = this;
        this.addListener('show', function () {
          me.modalMask.show(this.getDom().style.zIndex - 2);
        });
        this.addListener('hide', function () {
          me.modalMask.hide();
        });
        if (this.buttons) {
          for (var i = 0; i < this.buttons.length; i++) {
            this.buttons[i].postRender();
          }
        }
        domUtils.on(window, 'resize', function () {
          setTimeout(function () {
            if (!me.isHidden()) {
              me.safeSetOffset(uiUtils.getClientRect(me.getDom()));
            }
          });
        });
        this._hide();
      },
      mesureSize: function () {
        var body = this.getDom('body');
        var width = uiUtils.getClientRect(this.getDom('content')).width;
        var dialogBodyStyle = body.style;
        dialogBodyStyle.width = width;
        return uiUtils.getClientRect(body);
      },
      _onTitlebarMouseDown: function (evt, el) {
        if (this.draggable) {
          var rect;
          var vpRect = uiUtils.getViewportRect();
          var me = this;
          uiUtils.startDrag(evt, {
            ondragstart: function () {
              rect = uiUtils.getClientRect(me.getDom());
              me.getDom('contmask').style.visibility = 'visible';
              me.dragMask.show(me.getDom().style.zIndex - 1);
            },
            ondragmove: function (x, y) {
              var left = rect.left + x;
              var top = rect.top + y;
              me.safeSetOffset({ left: left, top: top });
            },
            ondragstop: function () {
              me.getDom('contmask').style.visibility = 'hidden';
              domUtils.removeClasses(me.getDom(), ['edui-state-centered']);
              me.dragMask.hide();
            },
          });
        }
      },
      reset: function () {
        this.getDom('content').innerHTML = this.getContentHtml();
        this.fireEvent('dialogafterreset');
      },
      _show: function () {
        if (this._hidden) {
          this.getDom().style.display = '';
          this.editor.container.style.zIndex &&
            (this.getDom().style.zIndex = this.editor.container.style.zIndex * 1 + 10);
          this._hidden = false;
          this.fireEvent('show');
          baidu.editor.ui.uiUtils.getFixedLayer().style.zIndex = this.getDom().style.zIndex - 4;
        }
      },
      isHidden: function () {
        return this._hidden;
      },
      _hide: function () {
        if (!this._hidden) {
          var wrapNode = this.getDom();
          wrapNode.style.display = 'none';
          wrapNode.style.zIndex = '';
          wrapNode.style.width = '';
          wrapNode.style.height = '';
          this._hidden = true;
          this.fireEvent('hide');
        }
      },
      open: function () {
        if (this.autoReset) {
          try {
            this.reset();
          } catch (e) {
            this.render();
            this.open();
          }
        }
        this.showAtCenter();
        if (this.iframeUrl) {
          try {
            this.getDom('iframe').focus();
          } catch (ex) {}
        }
        activeDialog = this;
      },
      _onCloseButtonClick: function (evt, el) {
        this.close(false);
      },
      close: function (ok) {
        if (this.fireEvent('close', ok) !== false) {
          if (this.fullscreen) {
            document.documentElement.style.overflowX = this._originalContext.html.overflowX;
            document.documentElement.style.overflowY = this._originalContext.html.overflowY;
            document.body.style.overflowX = this._originalContext.body.overflowX;
            document.body.style.overflowY = this._originalContext.body.overflowY;
            delete this._originalContext;
          }
          this._hide();
          var content = this.getDom('content');
          var iframe = this.getDom('iframe');
          if (content && iframe) {
            var doc = iframe.contentDocument || iframe.contentWindow.document;
            doc && (doc.body.innerHTML = '');
            domUtils.remove(content);
          }
        }
      },
    };
    utils.inherits(Dialog, UIBase);
  })();
  (function () {
    var utils = baidu.editor.utils,
      Menu = baidu.editor.ui.Menu,
      SplitButton = baidu.editor.ui.SplitButton,
      MenuButton = (baidu.editor.ui.MenuButton = function (options) {
        this.initOptions(options);
        this.initMenuButton();
      });
    MenuButton.prototype = {
      initMenuButton: function () {
        var me = this;
        this.uiName = 'menubutton';
        this.popup = new Menu({ items: me.items, className: me.className, editor: me.editor });
        this.popup.addListener('show', function () {
          var list = this;
          for (var i = 0; i < list.items.length; i++) {
            list.items[i].removeState('checked');
            if (list.items[i].value == me._value) {
              list.items[i].addState('checked');
              this.value = me._value;
            }
          }
        });
        this.initSplitButton();
      },
      setValue: function (value) {
        this._value = value;
      },
    };
    utils.inherits(MenuButton, SplitButton);
  })();
  (function () {
    var utils = baidu.editor.utils,
      Popup = baidu.editor.ui.Popup,
      SplitButton = baidu.editor.ui.SplitButton,
      MultiMenuPop = (baidu.editor.ui.MultiMenuPop = function (options) {
        this.initOptions(options);
        this.initMultiMenu();
      });
    MultiMenuPop.prototype = {
      initMultiMenu: function () {
        var me = this;
        this.popup = new Popup({
          content: '',
          editor: me.editor,
          iframe_rendered: false,
          onshow: function () {
            if (!this.iframe_rendered) {
              this.iframe_rendered = true;
              this.getDom('content').innerHTML =
                '<iframe id="' + me.id + '_iframe" src="' + me.iframeUrl + '" frameborder="0"></iframe>';
              me.editor.container.style.zIndex &&
                (this.getDom().style.zIndex = me.editor.container.style.zIndex * 1 + 1);
            }
          },
        });
        this.onbuttonclick = function () {
          this.showPopup();
        };
        this.initSplitButton();
      },
    };
    utils.inherits(MultiMenuPop, SplitButton);
  })();
  (function () {
    var UI = baidu.editor.ui,
      UIBase = UI.UIBase,
      uiUtils = UI.uiUtils,
      utils = baidu.editor.utils,
      domUtils = baidu.editor.dom.domUtils;
    var allMenus = [],
      timeID,
      isSubMenuShow = false;
    var ShortCutMenu = (UI.ShortCutMenu = function (options) {
      this.initOptions(options);
      this.initShortCutMenu();
    });
    ShortCutMenu.postHide = hideAllMenu;
    ShortCutMenu.prototype = {
      isHidden: true,
      SPACE: 5,
      initShortCutMenu: function () {
        this.items = this.items || [];
        this.initUIBase();
        this.initItems();
        this.initEvent();
        allMenus.push(this);
      },
      initEvent: function () {
        var me = this,
          doc = me.editor.document;
        me.editor.addListener('afterhidepop', function () {
          if (!me.isHidden) {
            isSubMenuShow = true;
          }
        });
      },
      initItems: function () {
        if (utils.isArray(this.items)) {
          for (var i = 0, len = this.items.length; i < len; i++) {
            if ('string' !== typeof this.items[i]) {
              continue;
            }
            var item = this.items[i].toLowerCase();
            if (UI[item]) {
              this.items[i] = new UI[item](this.editor);
              this.items[i]._name = item;
              this.items[i].className += ' edui-short-cut-sub-menu ';
            }
          }
        }
      },
      setOpacity: function (el, value) {
        if (browser.ie && browser.version < 9) {
          el.style.filter = 'alpha(opacity = ' + parseFloat(value) * 100 + ');';
        } else {
          el.style.opacity = value;
        }
      },
      getSubMenuMark: function () {
        isSubMenuShow = false;
        var layerEle = uiUtils.getFixedLayer();
        var list = domUtils.getElementsByTagName(layerEle, 'div', function (node) {
          return domUtils.hasClass(node, 'edui-short-cut-sub-menu edui-popup');
        });
        for (var i = 0, node; (node = list[i++]); ) {
          if (node.style.display !== 'none') {
            isSubMenuShow = true;
          }
        }
        return isSubMenuShow;
      },
      show: function (e, hasContextmenu) {
        var me = this,
          offset = {},
          el = this.getDom(),
          fixedlayer = uiUtils.getFixedLayer();
        var shortcutMenuShows = this.editor.options.shortcutMenuShows;
        for (let item of this.items) {
          if (item._name) {
            if (item._name in shortcutMenuShows) {
              item.uiShow(shortcutMenuShows[item._name]);
            }
          }
        }
        for (let item of this.items) {
          if ('shouldUiShow' in item) {
            item.uiShow(item.shouldUiShow());
          }
        }
        function setPos(offset) {
          if (offset.left < 0) {
            offset.left = 0;
          }
          if (offset.top < 0) {
            offset.top = 0;
          }
          el.style.cssText = 'position:absolute;left:' + offset.left + 'px;top:' + offset.top + 'px;';
        }
        function setPosByCxtMenu(menu) {
          if (!menu.tagName) {
            menu = menu.getDom();
          }
          offset.left = parseInt(menu.style.left);
          offset.top = parseInt(menu.style.top);
          offset.top -= el.offsetHeight + 15;
          setPos(offset);
        }
        me.eventType = e.type;
        el.style.cssText = 'display:block;left:-9999px';
        offset = uiUtils.getViewportOffsetByEvent(e);
        offset.top -= el.offsetHeight + me.SPACE;
        offset.left += me.SPACE + 20;
        setPos(offset);
        me.setOpacity(el, 1);
        me.isHidden = false;
        me.left = e.screenX + el.offsetWidth / 2 - me.SPACE;
        me.top = e.screenY - el.offsetHeight / 2 - me.SPACE;
        if (me.editor) {
          el.style.zIndex = me.editor.container.style.zIndex * 1 + 10;
          fixedlayer.style.zIndex = el.style.zIndex - 1;
        }
      },
      hide: function () {
        if (this.getDom()) {
          this.getDom().style.display = 'none';
        }
        this.isHidden = true;
      },
      postRender: function () {
        if (utils.isArray(this.items)) {
          for (var i = 0, item; (item = this.items[i++]); ) {
            item.postRender();
          }
        }
      },
      getHtmlTpl: function () {
        var buff;
        if (utils.isArray(this.items)) {
          buff = [];
          for (var i = 0; i < this.items.length; i++) {
            buff[i] = this.items[i].renderHtml();
          }
          buff = buff.join('');
        } else {
          buff = this.items;
        }
        return (
          '<div id="##" class="%% edui-toolbar" data-src="shortcutmenu" onmousedown="return false;" onselectstart="return false;" >' +
          buff +
          '</div>'
        );
      },
    };
    utils.inherits(ShortCutMenu, UIBase);
    function hideAllMenu(e) {
      var tgt = e.target || e.srcElement,
        cur = domUtils.findParent(
          tgt,
          function (node) {
            return domUtils.hasClass(node, 'edui-shortcutmenu') || domUtils.hasClass(node, 'edui-popup');
          },
          true,
        );
      if (!cur) {
        for (var i = 0, menu; (menu = allMenus[i++]); ) {
          menu.hide();
        }
      }
    }
    domUtils.on(document, 'mousedown', function (e) {
      hideAllMenu(e);
    });
    domUtils.on(window, 'scroll', function (e) {
      hideAllMenu(e);
    });
  })();
  (function () {
    var utils = baidu.editor.utils,
      UIBase = baidu.editor.ui.UIBase,
      Breakline = (baidu.editor.ui.Breakline = function (options) {
        this.initOptions(options);
        this.initSeparator();
      });
    Breakline.prototype = {
      uiName: 'Breakline',
      initSeparator: function () {
        this.initUIBase();
      },
      getHtmlTpl: function () {
        return '<br/>';
      },
    };
    utils.inherits(Breakline, UIBase);
  })();
  (function () {
    var utils = baidu.editor.utils,
      domUtils = baidu.editor.dom.domUtils,
      UIBase = baidu.editor.ui.UIBase,
      Message = (baidu.editor.ui.Message = function (options) {
        this.initOptions(options);
        this.initMessage();
      });
    Message.prototype = {
      initMessage: function () {
        this.initUIBase();
      },
      getHtmlTpl: function () {
        return (
          '<div id="##" class="edui-message %%">' +
          ' <div id="##_closer" class="edui-message-closer">×</div>' +
          ' <div id="##_body" class="edui-message-body edui-message-type-info">' +
          ' <iframe style="position:absolute;z-index:-1;left:0;top:0;background-color: transparent;" frameborder="0" width="100%" height="100%" src="about:blank"></iframe>' +
          ' <div class="edui-shadow"></div>' +
          ' <div id="##_content" class="edui-message-content">' +
          '  </div>' +
          ' </div>' +
          '</div>'
        );
      },
      reset: function (opt) {
        var me = this;
        if (!opt.keepshow) {
          clearTimeout(this.timer);
          me.timer = setTimeout(function () {
            me.hide();
          }, opt.timeout || 4e3);
        }
        opt.content !== undefined && me.setContent(opt.content);
        opt.type !== undefined && me.setType(opt.type);
        me.show();
      },
      postRender: function () {
        var me = this,
          closer = this.getDom('closer');
        closer &&
          domUtils.on(closer, 'click', function () {
            me.hide();
          });
      },
      setContent: function (content) {
        this.getDom('content').innerHTML = content;
      },
      setType: function (type) {
        type = type || 'info';
        var body = this.getDom('body');
        body.className = body.className.replace(/edui-message-type-[\w-]+/, 'edui-message-type-' + type);
      },
      getContent: function () {
        return this.getDom('content').innerHTML;
      },
      getType: function () {
        var arr = this.getDom('body').match(/edui-message-type-([\w-]+)/);
        return arr ? arr[1] : '';
      },
      show: function () {
        this.getDom().style.display = 'block';
      },
      hide: function () {
        var dom = this.getDom();
        if (dom) {
          dom.style.display = 'none';
          dom.parentNode && dom.parentNode.removeChild(dom);
        }
      },
    };
    utils.inherits(Message, UIBase);
  })();
  (function () {
    var utils = baidu.editor.utils;
    var editorui = baidu.editor.ui;
    var _Dialog = editorui.Dialog;
    editorui.buttons = {};
    editorui.Dialog = function (options) {
      var dialog = new _Dialog(options);
      dialog.addListener('hide', function () {
        if (dialog.editor) {
          var editor = dialog.editor;
          try {
            if (browser.gecko) {
              var y = editor.window.scrollY,
                x = editor.window.scrollX;
              editor.body.focus();
              editor.window.scrollTo(x, y);
            } else {
              editor.focus();
            }
          } catch (ex) {}
        }
      });
      return dialog;
    };
    var btnCmds = [
      'undo',
      'redo',
      'formatmatch',
      'bold',
      'italic',
      'underline',
      'fontborder',
      'touppercase',
      'tolowercase',
      'strikethrough',
      'subscript',
      'superscript',
      'source',
      'indent',
      'outdent',
      'blockquote',
      'pasteplain',
      'pagebreak',
      'selectall',
      'print',
      'horizontal',
      'removeformat',
      'time',
      'date',
      'unlink',
      'insertparagraphbeforetable',
      'insertrow',
      'insertcol',
      'mergeright',
      'mergedown',
      'deleterow',
      'deletecol',
      'splittorows',
      'splittocols',
      'splittocells',
      'mergecells',
      'deletetable',
    ];
    for (var i = 0, ci; (ci = btnCmds[i++]); ) {
      ci = ci.toLowerCase();
      editorui[ci] = (function (cmd) {
        return function (editor) {
          var ui = new editorui.Button({
            className: 'edui-for-' + cmd,
            title: editor.options.labelMap[cmd] || editor.getLang('labelMap.' + cmd) || '',
            onclick: function () {
              editor.execCommand(cmd);
            },
            theme: editor.options.theme,
            showText: false,
          });
          switch (cmd) {
            case 'bold':
            case 'italic':
            case 'underline':
            case 'strikethrough':
            case 'fontborder':
              ui.shouldUiShow = (function (cmdInternal) {
                return function () {
                  if (!editor.selection.getText()) {
                    return false;
                  }
                  return editor.queryCommandState(cmdInternal) !== UE.constants.STATEFUL.DISABLED;
                };
              })(cmd);
              break;
          }
          editorui.buttons[cmd] = ui;
          editor.addListener('selectionchange', function (type, causeByUi, uiReady) {
            var state = editor.queryCommandState(cmd);
            if (state === -1) {
              ui.setDisabled(true);
              ui.setChecked(false);
            } else {
              if (!uiReady) {
                ui.setDisabled(false);
                ui.setChecked(state);
              }
            }
          });
          return ui;
        };
      })(ci);
    }
    editorui.cleardoc = function (editor) {
      var ui = new editorui.Button({
        className: 'edui-for-cleardoc',
        title: editor.options.labelMap.cleardoc || editor.getLang('labelMap.cleardoc') || '',
        theme: editor.options.theme,
        onclick: function () {
          if (confirm(editor.getLang('confirmClear'))) {
            editor.execCommand('cleardoc');
          }
        },
      });
      editorui.buttons['cleardoc'] = ui;
      editor.addListener('selectionchange', function () {
        ui.setDisabled(editor.queryCommandState('cleardoc') == -1);
      });
      return ui;
    };
    var imageTypeSet = ['none', 'left', 'center', 'right'];
    for (let value of imageTypeSet) {
      (function (value) {
        editorui['image' + value] = function (editor) {
          var ui = new editorui.Button({
            className: 'edui-for-' + 'image' + value,
            title: editor.options.labelMap['image' + value] || editor.getLang('labelMap.' + 'image' + value) || '',
            theme: editor.options.theme,
            onclick: function () {
              editor.execCommand('imagefloat', value);
            },
            shouldUiShow: function () {
              let closedNode = editor.selection.getRange().getClosedNode();
              if (!closedNode || closedNode.tagName !== 'IMG') {
                return false;
              }
              if (domUtils.hasClass(closedNode, 'uep-loading') || domUtils.hasClass(closedNode, 'uep-loading-error')) {
                return false;
              }
              return editor.queryCommandState('imagefloat') !== UE.constants.STATEFUL.DISABLED;
            },
          });
          editorui.buttons['image' + value] = ui;
          editor.addListener('selectionchange', function (type, causeByUi, uiReady) {
            ui.setDisabled(editor.queryCommandState('imagefloat') === UE.constants.STATEFUL.DISABLED);
            ui.setChecked(editor.queryCommandValue('imagefloat') === value && !uiReady);
          });
          return ui;
        };
      })(value);
    }
    var typeset = { justify: ['left', 'right', 'center', 'justify'], directionality: ['ltr', 'rtl'] };
    for (var p in typeset) {
      (function (cmd, val) {
        for (var i = 0, ci; (ci = val[i++]); ) {
          (function (cmd2) {
            editorui[cmd.replace('float', '') + cmd2] = function (editor) {
              var ui = new editorui.Button({
                className: 'edui-for-' + cmd.replace('float', '') + cmd2,
                title:
                  editor.options.labelMap[cmd.replace('float', '') + cmd2] ||
                  editor.getLang('labelMap.' + cmd.replace('float', '') + cmd2) ||
                  '',
                theme: editor.options.theme,
                onclick: function () {
                  editor.execCommand(cmd, cmd2);
                },
              });
              editorui.buttons[cmd] = ui;
              editor.addListener('selectionchange', function (type, causeByUi, uiReady) {
                ui.setDisabled(editor.queryCommandState(cmd) == -1);
                ui.setChecked(editor.queryCommandValue(cmd) == cmd2 && !uiReady);
              });
              return ui;
            };
          })(ci);
        }
      })(p, typeset[p]);
    }
    for (var i = 0, ci; (ci = ['backcolor', 'forecolor'][i++]); ) {
      editorui[ci] = (function (cmd) {
        return function (editor) {
          var ui = new editorui.ColorButton({
            className: 'edui-for-' + cmd,
            color: 'default',
            title: editor.options.labelMap[cmd] || editor.getLang('labelMap.' + cmd) || '',
            editor: editor,
            onpickcolor: function (t, color) {
              editor.execCommand(cmd, color);
            },
            onpicknocolor: function () {
              editor.execCommand(cmd, 'default');
              this.setColor('transparent');
              this.color = 'default';
            },
            onbuttonclick: function () {
              editor.execCommand(cmd, this.color);
            },
            shouldUiShow: function () {
              if (!editor.selection.getText()) {
                return false;
              }
              return editor.queryCommandState(cmd) !== UE.constants.STATEFUL.DISABLED;
            },
          });
          editorui.buttons[cmd] = ui;
          editor.addListener('selectionchange', function () {
            ui.setDisabled(editor.queryCommandState(cmd) == -1);
          });
          return ui;
        };
      })(ci);
    }
    var dialogIframeUrlMap = {
      anchor: '~/dialogs/anchor/anchor.html?eb9739cc',
      insertimage: '~/dialogs/image/image.html?afbedf05',
      link: '~/dialogs/link/link.html?fa72bcd7',
      spechars: '~/dialogs/spechars/spechars.html?3b88f009',
      searchreplace: '~/dialogs/searchreplace/searchreplace.html?3167e75a',
      insertvideo: '~/dialogs/video/video.html?c2c9fa02',
      insertaudio: '~/dialogs/audio/audio.html?47891a09',
      help: '~/dialogs/help/help.html?4bb38d19',
      preview: '~/dialogs/preview/preview.html?b533ff4e',
      emotion: '~/dialogs/emotion/emotion.html?c5e06473',
      wordimage: '~/dialogs/wordimage/wordimage.html?6c25c600',
      formula: '~/dialogs/formula/formula.html?a3bc14af',
      attachment: '~/dialogs/attachment/attachment.html?8cf1bb27',
      insertframe: '~/dialogs/insertframe/insertframe.html?9353d50c',
      edittip: '~/dialogs/table/edittip.html?7f922949',
      edittable: '~/dialogs/table/edittable.html?c2a698ec',
      edittd: '~/dialogs/table/edittd.html?e110da33',
      scrawl: '~/dialogs/scrawl/scrawl.html?185f463e',
      template: '~/dialogs/template/template.html?4ec66ee4',
      background: '~/dialogs/background/background.html?63701ca2',
      contentimport: '~/dialogs/contentimport/contentimport.html?96da835f',
      ai: '~/dialogs/ai/ai.html?86145ec2',
    };
    var dialogBtns = {
      noOk: ['searchreplace', 'help', 'spechars', 'preview'],
      ok: [
        'attachment',
        'anchor',
        'link',
        'insertimage',
        'insertframe',
        'wordimage',
        'insertvideo',
        'insertaudio',
        'edittip',
        'edittable',
        'edittd',
        'scrawl',
        'template',
        'formula',
        'background',
        'contentimport',
      ],
    };
    for (var p in dialogBtns) {
      (function (type, vals) {
        for (var i = 0, ci; (ci = vals[i++]); ) {
          if (browser.opera && ci === 'searchreplace') {
            continue;
          }
          (function (cmd) {
            editorui[cmd] = function (editor, iframeUrl, title) {
              iframeUrl = iframeUrl || (editor.options.dialogIframeUrlMap || {})[cmd] || dialogIframeUrlMap[cmd];
              title = editor.options.labelMap[cmd] || editor.getLang('labelMap.' + cmd) || '';
              var dialog;
              if (iframeUrl) {
                dialog = new editorui.Dialog(
                  utils.extend(
                    {
                      iframeUrl: editor.ui.mapUrl(iframeUrl),
                      editor: editor,
                      className: 'edui-for-' + cmd,
                      title: title,
                      holdScroll: cmd === 'insertimage',
                      fullscreen: /preview/.test(cmd),
                      closeDialog: editor.getLang('closeDialog'),
                    },
                    type === 'ok'
                      ? {
                          buttons: [
                            {
                              className: 'edui-okbutton',
                              label: editor.getLang('ok'),
                              editor: editor,
                              onclick: function () {
                                dialog.close(true);
                              },
                            },
                            {
                              className: 'edui-cancelbutton',
                              label: editor.getLang('cancel'),
                              editor: editor,
                              onclick: function () {
                                dialog.close(false);
                              },
                            },
                          ],
                        }
                      : {},
                  ),
                );
                editor.ui._dialogs[cmd + 'Dialog'] = dialog;
              }
              var ui = new editorui.Button({
                className: 'edui-for-' + cmd,
                title: title,
                onclick: function () {
                  if (editor.options.toolbarCallback) {
                    if (true === editor.options.toolbarCallback(cmd, editor)) {
                      return;
                    }
                  }
                  if (dialog) {
                    switch (cmd) {
                      case 'wordimage':
                        var images = editor.execCommand('wordimage');
                        if (images && images.length) {
                          dialog.render();
                          dialog.open();
                        }
                        break;
                      case 'scrawl':
                        if (editor.queryCommandState('scrawl') !== -1) {
                          dialog.render();
                          dialog.open();
                        }
                        break;
                      default:
                        dialog.render();
                        dialog.open();
                    }
                  }
                },
                theme: editor.options.theme,
                disabled: cmd === 'scrawl' && editor.queryCommandState('scrawl') === -1,
              });
              switch (cmd) {
                case 'insertimage':
                case 'formula':
                  ui.shouldUiShow = (function (cmd) {
                    return function () {
                      let closedNode = editor.selection.getRange().getClosedNode();
                      if (!closedNode || closedNode.tagName !== 'IMG') {
                        return false;
                      }
                      if ('formula' === cmd && closedNode.getAttribute('data-formula-image') !== null) {
                        return true;
                      }
                      if ('insertimage' === cmd) {
                        return true;
                      }
                      return false;
                    };
                  })(cmd);
                  break;
              }
              editorui.buttons[cmd] = ui;
              editor.addListener('selectionchange', function () {
                var unNeedCheckState = { edittable: 1 };
                if (cmd in unNeedCheckState) return;
                var state = editor.queryCommandState(cmd);
                if (ui.getDom()) {
                  ui.setDisabled(state === -1);
                  ui.setChecked(state);
                }
              });
              return ui;
            };
          })(ci.toLowerCase());
        }
      })(p, dialogBtns[p]);
    }
    editorui.insertcode = function (editor, list, title) {
      list = editor.options['insertcode'] || [];
      title = editor.options.labelMap['insertcode'] || editor.getLang('labelMap.insertcode') || '';
      var items = [];
      utils.each(list, function (key, val) {
        items.push({
          label: key,
          value: val,
          theme: editor.options.theme,
          renderLabelHtml: function () {
            return '<div class="edui-label %%-label" >' + (this.label || '') + '</div>';
          },
        });
      });
      var ui = new editorui.Combox({
        editor: editor,
        items: items,
        onselect: function (t, index) {
          editor.execCommand('insertcode', this.items[index].value);
        },
        onbuttonclick: function () {
          this.showPopup();
        },
        title: title,
        initValue: title,
        className: 'edui-for-insertcode',
        indexByValue: function (value) {
          if (value) {
            for (var i = 0, ci; (ci = this.items[i]); i++) {
              if (ci.value.indexOf(value) != -1) return i;
            }
          }
          return -1;
        },
      });
      editorui.buttons['insertcode'] = ui;
      editor.addListener('selectionchange', function (type, causeByUi, uiReady) {
        if (!uiReady) {
          var state = editor.queryCommandState('insertcode');
          if (state == -1) {
            ui.setDisabled(true);
          } else {
            ui.setDisabled(false);
            var value = editor.queryCommandValue('insertcode');
            if (!value) {
              ui.setValue(title);
              return;
            }
            value && (value = value.replace(/['"]/g, '').split(',')[0]);
            ui.setValue(value);
          }
        }
      });
      return ui;
    };
    editorui.fontfamily = function (editor, list, title) {
      list = editor.options['fontfamily'] || [];
      title = editor.options.labelMap['fontfamily'] || editor.getLang('labelMap.fontfamily') || '';
      if (!list.length) return;
      for (var i = 0, ci, items = []; (ci = list[i]); i++) {
        var langLabel = editor.getLang('fontfamily')[ci.name] || '';
        (function (key, val) {
          items.push({
            label: key,
            value: val,
            theme: editor.options.theme,
            renderLabelHtml: function () {
              return (
                '<div class="edui-label %%-label" style="font-family:' +
                utils.unhtml(this.value) +
                '">' +
                (this.label || '') +
                '</div>'
              );
            },
          });
        })(ci.label || langLabel, ci.val);
      }
      var ui = new editorui.Combox({
        editor: editor,
        items: items,
        onselect: function (t, index) {
          editor.execCommand('FontFamily', this.items[index].value);
        },
        onbuttonclick: function () {
          this.showPopup();
        },
        title: title,
        initValue: title,
        className: 'edui-for-fontfamily',
        indexByValue: function (value) {
          if (value) {
            for (var i = 0, ci; (ci = this.items[i]); i++) {
              if (ci.value.indexOf(value) != -1) return i;
            }
          }
          return -1;
        },
      });
      editorui.buttons['fontfamily'] = ui;
      editor.addListener('selectionchange', function (type, causeByUi, uiReady) {
        if (!uiReady) {
          var state = editor.queryCommandState('FontFamily');
          if (state == -1) {
            ui.setDisabled(true);
          } else {
            ui.setDisabled(false);
            var value = editor.queryCommandValue('FontFamily');
            value && (value = value.replace(/['"]/g, '').split(',')[0]);
            ui.setValue(value);
          }
        }
      });
      return ui;
    };
    editorui.fontsize = function (editor, list, title) {
      title = editor.options.labelMap['fontsize'] || editor.getLang('labelMap.fontsize') || '';
      list = list || editor.options['fontsize'] || [];
      if (!list.length) return;
      var items = [];
      for (var i = 0; i < list.length; i++) {
        var size = list[i] + 'px';
        items.push({
          label: size,
          value: size,
          theme: editor.options.theme,
          renderLabelHtml: function () {
            return (
              '<div class="edui-label %%-label" style="line-height:1;font-size:' +
              this.value +
              '">' +
              (this.label || '') +
              '</div>'
            );
          },
        });
      }
      var ui = new editorui.Combox({
        editor: editor,
        items: items,
        title: title,
        initValue: title,
        onselect: function (t, index) {
          editor.execCommand('FontSize', this.items[index].value);
        },
        onbuttonclick: function () {
          this.showPopup();
        },
        className: 'edui-for-fontsize',
      });
      editorui.buttons['fontsize'] = ui;
      editor.addListener('selectionchange', function (type, causeByUi, uiReady) {
        if (!uiReady) {
          var state = editor.queryCommandState('FontSize');
          if (state == -1) {
            ui.setDisabled(true);
          } else {
            ui.setDisabled(false);
            ui.setValue(editor.queryCommandValue('FontSize'));
          }
        }
      });
      return ui;
    };
    editorui.paragraph = function (editor, list, title) {
      title = editor.options.labelMap['paragraph'] || editor.getLang('labelMap.paragraph') || '';
      list = editor.options['paragraph'] || [];
      if (utils.isEmptyObject(list)) return;
      var items = [];
      for (var i in list) {
        items.push({
          value: i,
          label: list[i] || editor.getLang('paragraph')[i],
          theme: editor.options.theme,
          renderLabelHtml: function () {
            return (
              '<div class="edui-label %%-label"><span class="edui-for-' +
              this.value +
              '">' +
              (this.label || '') +
              '</span></div>'
            );
          },
        });
      }
      var ui = new editorui.Combox({
        editor: editor,
        items: items,
        title: title,
        initValue: title,
        className: 'edui-for-paragraph',
        onselect: function (t, index) {
          editor.execCommand('Paragraph', this.items[index].value);
        },
        onbuttonclick: function () {
          this.showPopup();
        },
      });
      editorui.buttons['paragraph'] = ui;
      editor.addListener('selectionchange', function (type, causeByUi, uiReady) {
        if (!uiReady) {
          var state = editor.queryCommandState('Paragraph');
          if (state == -1) {
            ui.setDisabled(true);
          } else {
            ui.setDisabled(false);
            var value = editor.queryCommandValue('Paragraph');
            var index = ui.indexByValue(value);
            if (index != -1) {
              ui.setValue(value);
            } else {
              ui.setValue(ui.initValue);
            }
          }
        }
      });
      return ui;
    };
    editorui.customstyle = function (editor) {
      var list = editor.options['customstyle'] || [],
        title = editor.options.labelMap['customstyle'] || editor.getLang('labelMap.customstyle') || '';
      if (!list.length) return;
      var langCs = editor.getLang('customstyle');
      for (var i = 0, items = [], t; (t = list[i++]); ) {
        (function (t) {
          var ck = {};
          ck.label = t.label ? t.label : langCs[t.name];
          ck.style = t.style;
          ck.className = t.className;
          ck.tag = t.tag;
          items.push({
            label: ck.label,
            value: ck,
            theme: editor.options.theme,
            renderLabelHtml: function () {
              return (
                '<div class="edui-label %%-label">' +
                '<' +
                ck.tag +
                ' ' +
                (ck.className ? ' class="' + ck.className + '"' : '') +
                (ck.style ? ' style="' + ck.style + '"' : '') +
                '>' +
                ck.label +
                '</' +
                ck.tag +
                '>' +
                '</div>'
              );
            },
          });
        })(t);
      }
      var ui = new editorui.Combox({
        editor: editor,
        items: items,
        title: title,
        initValue: title,
        className: 'edui-for-customstyle',
        onselect: function (t, index) {
          editor.execCommand('customstyle', this.items[index].value);
        },
        onbuttonclick: function () {
          this.showPopup();
        },
        indexByValue: function (value) {
          for (var i = 0, ti; (ti = this.items[i++]); ) {
            if (ti.label == value) {
              return i - 1;
            }
          }
          return -1;
        },
      });
      editorui.buttons['customstyle'] = ui;
      editor.addListener('selectionchange', function (type, causeByUi, uiReady) {
        if (!uiReady) {
          var state = editor.queryCommandState('customstyle');
          if (state == -1) {
            ui.setDisabled(true);
          } else {
            ui.setDisabled(false);
            var value = editor.queryCommandValue('customstyle');
            var index = ui.indexByValue(value);
            if (index != -1) {
              ui.setValue(value);
            } else {
              ui.setValue(ui.initValue);
            }
          }
        }
      });
      return ui;
    };
    editorui.inserttable = function (editor, iframeUrl, title) {
      title = editor.options.labelMap['inserttable'] || editor.getLang('labelMap.inserttable') || '';
      var ui = new editorui.TableButton({
        editor: editor,
        title: title,
        className: 'edui-for-inserttable',
        onpicktable: function (t, numCols, numRows) {
          editor.execCommand('InsertTable', { numRows: numRows, numCols: numCols, border: 1 });
        },
        onbuttonclick: function () {
          this.showPopup();
        },
      });
      editorui.buttons['inserttable'] = ui;
      editor.addListener('selectionchange', function () {
        ui.setDisabled(editor.queryCommandState('inserttable') == -1);
      });
      return ui;
    };
    editorui.lineheight = function (editor) {
      var val = editor.options.lineheight || [];
      if (!val.length) return;
      for (var i = 0, ci, items = []; (ci = val[i++]); ) {
        items.push({
          label: ci,
          value: ci,
          theme: editor.options.theme,
          onclick: function () {
            editor.execCommand('lineheight', this.value);
          },
        });
      }
      var ui = new editorui.MenuButton({
        editor: editor,
        className: 'edui-for-lineheight',
        title: editor.options.labelMap['lineheight'] || editor.getLang('labelMap.lineheight') || '',
        items: items,
        onbuttonclick: function () {
          var value = editor.queryCommandValue('LineHeight') || this.value;
          editor.execCommand('LineHeight', value);
        },
      });
      editorui.buttons['lineheight'] = ui;
      editor.addListener('selectionchange', function () {
        var state = editor.queryCommandState('LineHeight');
        if (state == -1) {
          ui.setDisabled(true);
        } else {
          ui.setDisabled(false);
          var value = editor.queryCommandValue('LineHeight');
          value && ui.setValue((value + '').replace(/cm/, ''));
          ui.setChecked(state);
        }
      });
      return ui;
    };
    var rowspacings = ['top', 'bottom'];
    for (var r = 0, ri; (ri = rowspacings[r++]); ) {
      (function (cmd) {
        editorui['rowspacing' + cmd] = function (editor) {
          var val = editor.options['rowspacing' + cmd] || [];
          if (!val.length) return null;
          for (var i = 0, ci, items = []; (ci = val[i++]); ) {
            items.push({
              label: ci,
              value: ci,
              theme: editor.options.theme,
              onclick: function () {
                editor.execCommand('rowspacing', this.value, cmd);
              },
            });
          }
          var ui = new editorui.MenuButton({
            editor: editor,
            className: 'edui-for-rowspacing' + cmd,
            title: editor.options.labelMap['rowspacing' + cmd] || editor.getLang('labelMap.rowspacing' + cmd) || '',
            items: items,
            onbuttonclick: function () {
              var value = editor.queryCommandValue('rowspacing', cmd) || this.value;
              editor.execCommand('rowspacing', value, cmd);
            },
          });
          editorui.buttons[cmd] = ui;
          editor.addListener('selectionchange', function () {
            var state = editor.queryCommandState('rowspacing', cmd);
            if (state == -1) {
              ui.setDisabled(true);
            } else {
              ui.setDisabled(false);
              var value = editor.queryCommandValue('rowspacing', cmd);
              value && ui.setValue((value + '').replace(/%/, ''));
              ui.setChecked(state);
            }
          });
          return ui;
        };
      })(ri);
    }
    var lists = ['insertorderedlist', 'insertunorderedlist'];
    for (var l = 0, cl; (cl = lists[l++]); ) {
      (function (cmd) {
        editorui[cmd] = function (editor) {
          var vals = editor.options[cmd],
            _onMenuClick = function () {
              editor.execCommand(cmd, this.value);
            },
            items = [];
          for (var i in vals) {
            items.push({
              label: vals[i] || editor.getLang()[cmd][i] || '',
              value: i,
              theme: editor.options.theme,
              onclick: _onMenuClick,
            });
          }
          var ui = new editorui.MenuButton({
            editor: editor,
            className: 'edui-for-' + cmd,
            title: editor.getLang('labelMap.' + cmd) || '',
            items: items,
            onbuttonclick: function () {
              var value = editor.queryCommandValue(cmd) || this.value;
              editor.execCommand(cmd, value);
            },
          });
          editorui.buttons[cmd] = ui;
          editor.addListener('selectionchange', function () {
            var state = editor.queryCommandState(cmd);
            if (state == -1) {
              ui.setDisabled(true);
            } else {
              ui.setDisabled(false);
              var value = editor.queryCommandValue(cmd);
              ui.setValue(value);
              ui.setChecked(state);
            }
          });
          return ui;
        };
      })(cl);
    }
    editorui.fullscreen = function (editor, title) {
      title = editor.options.labelMap['fullscreen'] || editor.getLang('labelMap.fullscreen') || '';
      var ui = new editorui.Button({
        className: 'edui-for-fullscreen',
        title: title,
        theme: editor.options.theme,
        onclick: function () {
          if (editor.ui) {
            editor.ui.setFullScreen(!editor.ui.isFullScreen());
          }
          this.setChecked(editor.ui.isFullScreen());
        },
      });
      editorui.buttons['fullscreen'] = ui;
      editor.addListener('selectionchange', function () {
        var state = editor.queryCommandState('fullscreen');
        ui.setDisabled(state == -1);
        ui.setChecked(editor.ui.isFullScreen());
      });
      return ui;
    };
    editorui['emotion'] = function (editor, iframeUrl) {
      var cmd = 'emotion';
      var ui = new editorui.MultiMenuPop({
        title: editor.options.labelMap[cmd] || editor.getLang('labelMap.' + cmd + '') || '',
        editor: editor,
        className: 'edui-for-' + cmd,
        iframeUrl: editor.ui.mapUrl(
          iframeUrl || (editor.options.dialogIframeUrlMap || {})[cmd] || dialogIframeUrlMap[cmd],
        ),
      });
      editorui.buttons[cmd] = ui;
      editor.addListener('selectionchange', function () {
        ui.setDisabled(editor.queryCommandState(cmd) == -1);
      });
      return ui;
    };
    editorui['autotypeset'] = function (editor) {
      var ui = new editorui.AutoTypeSetButton({
        editor: editor,
        title: editor.options.labelMap['autotypeset'] || editor.getLang('labelMap.autotypeset') || '',
        className: 'edui-for-autotypeset',
        onbuttonclick: function () {
          editor.execCommand('autotypeset');
        },
      });
      editorui.buttons['autotypeset'] = ui;
      editor.addListener('selectionchange', function () {
        ui.setDisabled(editor.queryCommandState('autotypeset') == -1);
      });
      return ui;
    };
    editorui['ai'] = function (editor, iframeUrl, title) {
      iframeUrl = iframeUrl || (editor.options.dialogIframeUrlMap || {})['ai'] || dialogIframeUrlMap['ai'];
      title = editor.options.labelMap['ai'] || editor.getLang('labelMap.ai') || '';
      var dialog = new editorui.Dialog({
        iframeUrl: editor.ui.mapUrl(iframeUrl),
        editor: editor,
        className: 'edui-for-ai',
        title: title,
        holdScroll: true,
        fullscreen: false,
        closeDialog: editor.getLang('closeDialog'),
      });
      editor.ui._dialogs['aiDialog'] = dialog;
      var ui = new editorui.Button({
        className: 'edui-for-ai',
        title: title,
        onclick: function () {
          if (editor.options.toolbarCallback) {
            if (true === editor.options.toolbarCallback('ai', editor)) {
              return;
            }
          }
          dialog.render();
          dialog.open();
        },
        theme: editor.options.theme,
        disabled: false,
      });
      editorui.buttons['ai'] = ui;
      return ui;
    };
    editorui['simpleupload'] = function (editor) {
      var name = 'simpleupload',
        ui = new editorui.Button({
          className: 'edui-for-' + name,
          title: editor.options.labelMap[name] || editor.getLang('labelMap.' + name) || '',
          onclick: function () {},
          theme: editor.options.theme,
          showText: false,
        });
      editorui.buttons[name] = ui;
      editor.addListener('ready', function () {
        var b = ui.getDom('body'),
          iconSpan = b.children[0];
        editor.fireEvent('simpleuploadbtnready', iconSpan);
      });
      editor.addListener('selectionchange', function (type, causeByUi, uiReady) {
        var state = editor.queryCommandState(name);
        if (state == -1) {
          ui.setDisabled(true);
          ui.setChecked(false);
        } else {
          if (!uiReady) {
            ui.setDisabled(false);
            ui.setChecked(state);
          }
        }
      });
      return ui;
    };
  })();
  (function () {
    var utils = baidu.editor.utils,
      uiUtils = baidu.editor.ui.uiUtils,
      UIBase = baidu.editor.ui.UIBase,
      domUtils = baidu.editor.dom.domUtils;
    var nodeStack = [];
    function EditorUI(options) {
      this.initOptions(options);
      this.initEditorUI();
    }
    EditorUI.prototype = {
      uiName: 'editor',
      initEditorUI: function () {
        this.editor.ui = this;
        this._dialogs = {};
        this.initUIBase();
        this._initToolbars();
        var editor = this.editor,
          me = this;
        editor.addListener('ready', function () {
          editor.getDialog = function (name) {
            return editor.ui._dialogs[name + 'Dialog'];
          };
          domUtils.on(editor.window, 'scroll', function (evt) {
            baidu.editor.ui.Popup.postHide(evt);
          });
          editor.ui._actualFrameWidth = editor.options.initialFrameWidth;
          UE.browser.ie &&
            UE.browser.version === 6 &&
            editor.container.ownerDocument.execCommand('BackgroundImageCache', false, true);
          if (editor.options.elementPathEnabled) {
            editor.ui.getDom('elementpath').innerHTML =
              '<div class="edui-editor-breadcrumb">' + editor.getLang('elementPathTip') + ':</div>';
          }
          if (editor.options.wordCount) {
            function countFn() {
              setCount(editor, me);
              domUtils.un(editor.document, 'click', arguments.callee);
            }
            domUtils.on(editor.document, 'click', countFn);
            editor.ui.getDom('wordcount').innerHTML = editor.getLang('wordCountTip');
          }
          editor.ui._scale();
          if (editor.options.scaleEnabled) {
            if (editor.autoHeightEnabled) {
              editor.disableAutoHeight();
            }
            me.enableScale();
          } else {
            me.disableScale();
          }
          if (!editor.options.elementPathEnabled && !editor.options.wordCount && !editor.options.scaleEnabled) {
            editor.ui.getDom('elementpath').style.display = 'none';
            editor.ui.getDom('wordcount').style.display = 'none';
            editor.ui.getDom('scale').style.display = 'none';
          }
          if (!editor.selection.isFocus()) return;
          editor.fireEvent('selectionchange', false, true);
        });
        editor.addListener('mousedown', function (t, evt) {
          var el = evt.target || evt.srcElement;
          baidu.editor.ui.Popup.postHide(evt, el);
          baidu.editor.ui.ShortCutMenu.postHide(evt);
        });
        editor.addListener('delcells', function () {
          if (UE.ui['edittip']) {
            new UE.ui['edittip'](editor);
          }
          editor.getDialog('edittip').open();
        });
        var pastePop,
          isPaste = false,
          timer;
        editor.addListener('afterpaste', function () {
          if (editor.queryCommandState('pasteplain')) return;
          if (baidu.editor.ui.PastePicker) {
            pastePop = new baidu.editor.ui.Popup({
              content: new baidu.editor.ui.PastePicker({ editor: editor }),
              editor: editor,
              className: 'edui-wordpastepop',
            });
            pastePop.render();
          }
          isPaste = true;
        });
        editor.addListener('afterinserthtml', function () {
          clearTimeout(timer);
          timer = setTimeout(function () {
            if (pastePop && (isPaste || editor.ui._isTransfer)) {
              if (pastePop.isHidden()) {
                var span = domUtils.createElement(editor.document, 'span', {
                    style: 'line-height:0px;',
                    innerHTML: '\ufeff',
                  }),
                  range = editor.selection.getRange();
                range.insertNode(span);
                var tmp = getDomNode(span, 'firstChild', 'previousSibling');
                tmp && pastePop.showAnchor(tmp.nodeType == 3 ? tmp.parentNode : tmp);
                domUtils.remove(span);
              } else {
                pastePop.show();
              }
              delete editor.ui._isTransfer;
              isPaste = false;
            }
          }, 200);
        });
        editor.addListener('contextmenu', function (t, evt) {
          baidu.editor.ui.Popup.postHide(evt);
        });
        editor.addListener('keydown', function (t, evt) {
          if (pastePop) pastePop.dispose(evt);
          var keyCode = evt.keyCode || evt.which;
          if (evt.altKey && keyCode == 90) {
            UE.ui.buttons['fullscreen'].onclick();
          }
        });
        editor.addListener('wordcount', function (type) {
          setCount(this, me);
        });
        function setCount(editor, ui) {
          editor.setOpt({
            wordCount: true,
            maximumWords: 1e4,
            wordCountMsg: editor.options.wordCountMsg || editor.getLang('wordCountMsg'),
            wordOverFlowMsg: editor.options.wordOverFlowMsg || editor.getLang('wordOverFlowMsg'),
          });
          var opt = editor.options,
            max = opt.maximumWords,
            msg = opt.wordCountMsg,
            errMsg = opt.wordOverFlowMsg,
            countDom = ui.getDom('wordcount');
          if (!opt.wordCount) {
            return;
          }
          var count = editor.getContentLength(true);
          if (count > max) {
            countDom.innerHTML = errMsg;
            editor.fireEvent('wordcountoverflow');
          } else {
            countDom.innerHTML = msg.replace('{#leave}', max - count).replace('{#count}', count);
          }
        }
        editor.addListener('selectionchange', function () {
          if (editor.options.elementPathEnabled) {
            me[(editor.queryCommandState('elementpath') == -1 ? 'dis' : 'en') + 'ableElementPath']();
          }
          if (editor.options.scaleEnabled) {
            me[(editor.queryCommandState('scale') == -1 ? 'dis' : 'en') + 'ableScale']();
          }
        });
        var popup = new baidu.editor.ui.Popup({
          editor: editor,
          content: '',
          className: 'edui-bubble',
          _onEditButtonClick: function () {
            this.hide();
            editor.ui._dialogs.linkDialog.open();
          },
          _onImgEditButtonClick: function (name) {
            this.hide();
            editor.ui._dialogs[name] && editor.ui._dialogs[name].open();
          },
          _onImgSetFloat: function (value) {
            this.hide();
            editor.execCommand('imagefloat', value);
          },
          _setIframeAlign: function (value) {
            var frame = popup.anchorEl;
            var newFrame = frame.cloneNode(true);
            switch (value) {
              case -2:
                newFrame.setAttribute('align', '');
                break;
              case -1:
                newFrame.setAttribute('align', 'left');
                break;
              case 1:
                newFrame.setAttribute('align', 'right');
                break;
            }
            frame.parentNode.insertBefore(newFrame, frame);
            domUtils.remove(frame);
            popup.anchorEl = newFrame;
            popup.showAnchor(popup.anchorEl);
          },
          _updateIframe: function () {
            var frame = (editor._iframe = popup.anchorEl);
            if (domUtils.hasClass(frame, 'ueditor_baidumap')) {
              editor.selection.getRange().selectNode(frame).select();
              editor.ui._dialogs.mapDialog.open();
              popup.hide();
            } else {
              editor.ui._dialogs.insertframeDialog.open();
              popup.hide();
            }
          },
          _onRemoveButtonClick: function (cmdName) {
            editor.execCommand(cmdName);
            this.hide();
          },
          queryAutoHide: function (el) {
            if (el && el.ownerDocument == editor.document) {
              if (el.tagName.toLowerCase() == 'img' || domUtils.findParentByTagName(el, 'a', true)) {
                return el !== popup.anchorEl;
              }
            }
            return baidu.editor.ui.Popup.prototype.queryAutoHide.call(this, el);
          },
        });
        popup.render();
        if (editor.options.imagePopup) {
          editor.addListener('mouseover', function (t, evt) {
            evt = evt || window.event;
            var el = evt.target || evt.srcElement;
            if (editor.ui._dialogs.insertframeDialog && /iframe/gi.test(el.tagName)) {
              var html = popup.formatHtml(
                '<nobr>' +
                  '<span onclick=$$._setIframeAlign(-2) class="edui-clickable">' +
                  editor.getLang('default') +
                  '</span>&nbsp;&nbsp;<span onclick=$$._setIframeAlign(-1) class="edui-clickable">' +
                  editor.getLang('justifyleft') +
                  '</span>&nbsp;&nbsp;<span onclick=$$._setIframeAlign(1) class="edui-clickable">' +
                  editor.getLang('justifyright') +
                  '</span>&nbsp;&nbsp;' +
                  ' <span onclick="$$._updateIframe( this);" class="edui-clickable">' +
                  editor.getLang('modify') +
                  '</span></nobr>',
              );
              if (html) {
                popup.getDom('content').innerHTML = html;
                popup.anchorEl = el;
                popup.showAnchor(popup.anchorEl);
              } else {
                popup.hide();
              }
            }
          });
          editor.addListener('selectionchange', function (t, causeByUi) {
            if (!causeByUi) {
              return;
            }
            var html = '',
              str = '',
              closedNode = editor.selection.getRange().getClosedNode(),
              dialogs = editor.ui._dialogs;
            if (closedNode && closedNode.tagName === 'IMG') {
              var dialogName = 'insertimageDialog';
              if (
                closedNode.className.indexOf('edui-faked-video') !== -1 ||
                closedNode.className.indexOf('edui-upload-video') !== -1
              ) {
                dialogName = 'insertvideoDialog';
              }
              if (
                closedNode.className.indexOf('edui-faked-audio') !== -1 ||
                closedNode.className.indexOf('edui-upload-audio') !== -1
              ) {
                dialogName = 'insertaudioDialog';
              }
              if (closedNode.getAttribute('anchorname')) {
                dialogName = 'anchorDialog';
                html = popup.formatHtml(
                  '<nobr>' +
                    '<span onclick=$$._onImgEditButtonClick("anchorDialog") class="edui-clickable">' +
                    editor.getLang('modify') +
                    '</span>&nbsp;&nbsp;' +
                    '<span onclick=$$._onRemoveButtonClick(\'anchor\') class="edui-clickable">' +
                    editor.getLang('delete') +
                    '</span></nobr>',
                );
              }
              if (domUtils.hasClass(closedNode, 'uep-loading') || domUtils.hasClass(closedNode, 'uep-loading-error')) {
                dialogName = '';
              }
              if (!dialogs[dialogName]) {
                return;
              }
              var actions = [];
              if (closedNode.getAttribute('data-word-image')) {
                actions.push(
                  "<span onclick=\"$$._onImgEditButtonClick('wordimageDialog');\" class='edui-clickable edui-popup-action-item'>" +
                    editor.getLang('save') +
                    '</span>',
                );
              } else {
              }
              if (actions.length > 0) {
                actions.unshift('<nobr>');
                actions.push('</nobr>');
              }
              !html && (html = popup.formatHtml(actions.join('')));
            }
            if (editor.ui._dialogs.linkDialog) {
              var link = editor.queryCommandValue('link');
              var url;
              if (link && (url = link.getAttribute('_href') || link.getAttribute('href', 2))) {
                var txt = url;
                if (url.length > 30) {
                  txt = url.substring(0, 20) + '...';
                }
                if (html) {
                  html += '<div style="height:5px;"></div>';
                }
                html += popup.formatHtml(
                  '<nobr>' +
                    editor.getLang('anchorMsg') +
                    ': <a target="_blank" href="' +
                    url +
                    '" title="' +
                    url +
                    '" >' +
                    txt +
                    '</a>' +
                    ' <span class="edui-clickable" onclick="$$._onEditButtonClick();">' +
                    editor.getLang('modify') +
                    '</span>' +
                    ' <span class="edui-clickable" onclick="$$._onRemoveButtonClick(\'unlink\');"> ' +
                    editor.getLang('clear') +
                    '</span></nobr>',
                );
                popup.showAnchor(link);
              }
            }
            if (html) {
              popup.getDom('content').innerHTML = html;
              popup.anchorEl = closedNode || link;
              popup.showAnchor(popup.anchorEl);
            } else {
              popup.hide();
            }
          });
        }
      },
      _initToolbars: function () {
        var me = this;
        var editor = this.editor;
        var toolbars = this.toolbars || [];
        if (toolbars[0]) {
          toolbars[0].unshift('message');
        }
        var toolbarUis = [];
        var extraUIs = [];
        for (var i = 0; i < toolbars.length; i++) {
          var toolbar = toolbars[i];
          var toolbarUi = new baidu.editor.ui.Toolbar({ theme: editor.options.theme });
          for (var j = 0; j < toolbar.length; j++) {
            var toolbarItem = toolbar[j];
            var toolbarItemUi = null;
            if (typeof toolbarItem == 'string') {
              toolbarItem = toolbarItem.toLowerCase();
              if (toolbarItem === '|') {
                toolbarItem = 'Separator';
              }
              if (toolbarItem === '||') {
                toolbarItem = 'Breakline';
              }
              var ui = baidu.editor.ui[toolbarItem];
              if (ui) {
                if (utils.isFunction(ui)) {
                  toolbarItemUi = new baidu.editor.ui[toolbarItem](editor);
                  toolbarItemUi._name = toolbarItem;
                } else {
                  if (ui.id && ui.id !== editor.key) {
                    continue;
                  }
                  var itemUI = ui.execFn.call(editor, editor, toolbarItem);
                  if (itemUI) {
                    itemUI._name = toolbarItem;
                    if (ui.index === undefined) {
                      toolbarUi.add(itemUI);
                      continue;
                    } else {
                      extraUIs.push({ index: ui.index, itemUI: itemUI });
                    }
                  }
                }
              }
              if (toolbarItem === 'fullscreen') {
                if (toolbarUis && toolbarUis[0]) {
                  toolbarUis[0].items.splice(0, 0, toolbarItemUi);
                } else {
                  toolbarItemUi && toolbarUi.items.splice(0, 0, toolbarItemUi);
                }
                continue;
              }
            } else {
              toolbarItemUi = toolbarItem;
            }
            if (toolbarItemUi && toolbarItemUi.id) {
              toolbarUi.add(toolbarItemUi);
            }
          }
          toolbarUis[i] = toolbarUi;
        }
        utils.each(extraUIs, function (obj) {
          toolbarUi.add(obj.itemUI, obj.index);
        });
        this.toolbars = toolbarUis;
        editor.addListener('serverConfigLoaded', function () {
          me.refreshToolbars();
        });
        setTimeout(() => {
          this.refreshToolbars();
        }, 0);
      },
      refreshToolbars: function () {
        var toolbarShows = this.editor.options.toolbarShows;
        for (var i = 0; i < this.toolbars.length; i++) {
          for (var j = 0; j < this.toolbars[i].items.length; j++) {
            var item = this.toolbars[i].items[j];
            if (item._name) {
              if (item._name in toolbarShows) {
                item.uiShow(toolbarShows[item._name]);
              }
            }
          }
        }
      },
      getHtmlTpl: function () {
        return (
          '<div id="##" class="%%">' +
          '<div id="##_toolbarbox" class="%%-toolbarbox">' +
          (this.toolbars.length
            ? '<div id="##_toolbarboxouter" class="%%-toolbarboxouter"><div class="%%-toolbarboxinner">' +
              this.renderToolbarBoxHtml() +
              '</div></div>'
            : '') +
          '<div id="##_toolbarmsg" class="%%-toolbarmsg" style="display:none;">' +
          '<div id = "##_upload_dialog" class="%%-toolbarmsg-upload" onclick="$$.showWordImageDialog();">' +
          this.editor.getLang('clickToUpload') +
          '</div>' +
          '<div class="%%-toolbarmsg-close" onclick="$$.hideToolbarMsg();">x</div>' +
          '<div id="##_toolbarmsg_label" class="%%-toolbarmsg-label"></div>' +
          '<div style="height:0;overflow:hidden;clear:both;"></div>' +
          '</div>' +
          '<div id="##_message_holder" class="%%-messageholder"></div>' +
          '</div>' +
          '<div id="##_iframeholder" class="%%-iframeholder">' +
          '</div>' +
          '<div id="##_bottombar" class="%%-bottomContainer"><table><tr>' +
          '<td id="##_elementpath" class="%%-bottombar"></td>' +
          '<td id="##_wordcount" class="%%-wordcount"></td>' +
          '<td id="##_scale" class="%%-scale"><div class="%%-icon"></div></td>' +
          '</tr></table></div>' +
          '<div id="##_scalelayer"></div>' +
          '</div>'
        );
      },
      showWordImageDialog: function () {
        this._dialogs['wordimageDialog'].open();
      },
      renderToolbarBoxHtml: function () {
        var buff = [];
        for (var i = 0; i < this.toolbars.length; i++) {
          buff.push(this.toolbars[i].renderHtml());
        }
        return buff.join('');
      },
      setFullScreen: function (fullscreen) {
        var editor = this.editor,
          container = editor.container.parentNode.parentNode;
        if (this._fullscreen != fullscreen) {
          this._fullscreen = fullscreen;
          this.editor.fireEvent('beforefullscreenchange', fullscreen);
          if (baidu.editor.browser.gecko) {
            var bk = editor.selection.getRange().createBookmark();
          }
          if (fullscreen) {
            this._bakEditorContaninerWidth = editor.iframe.parentNode.style.width;
            while (container.tagName !== 'BODY') {
              var position = baidu.editor.dom.domUtils.getComputedStyle(container, 'position');
              nodeStack.push(position);
              container.style.position = 'static';
              container = container.parentNode;
            }
            this._bakHtmlOverflow = document.documentElement.style.overflow;
            this._bakBodyOverflow = document.body.style.overflow;
            this._bakAutoHeight = this.editor.autoHeightEnabled;
            this._bakScrollTop = Math.max(document.documentElement.scrollTop, document.body.scrollTop);
            if (this._bakAutoHeight) {
              editor.autoHeightEnabled = false;
              this.editor.disableAutoHeight();
            }
            document.documentElement.style.overflow = 'hidden';
            window.scrollTo(0, window.scrollY);
            this._bakCssText = this.getDom().style.cssText;
            this._bakCssText1 = this.getDom('iframeholder').style.cssText;
            editor.iframe.parentNode.style.width = '';
            this._updateFullScreen();
          } else {
            while (container.tagName !== 'BODY') {
              container.style.position = nodeStack.shift();
              container = container.parentNode;
            }
            this.getDom().style.cssText = this._bakCssText;
            this.getDom('iframeholder').style.cssText = this._bakCssText1;
            if (this._bakAutoHeight) {
              editor.autoHeightEnabled = true;
              this.editor.enableAutoHeight();
            }
            document.documentElement.style.overflow = this._bakHtmlOverflow;
            document.body.style.overflow = this._bakBodyOverflow;
            editor.iframe.parentNode.style.width = this._bakEditorContaninerWidth;
            window.scrollTo(0, this._bakScrollTop);
          }
          if (browser.gecko && editor.body.contentEditable === 'true') {
            var input = document.createElement('input');
            document.body.appendChild(input);
            editor.body.contentEditable = false;
            setTimeout(function () {
              input.focus();
              setTimeout(function () {
                editor.body.contentEditable = true;
                editor.fireEvent('fullscreenchanged', fullscreen);
                editor.selection.getRange().moveToBookmark(bk).select(true);
                baidu.editor.dom.domUtils.remove(input);
                fullscreen && window.scroll(0, 0);
              }, 0);
            }, 0);
          }
          if (editor.body.contentEditable === 'true') {
            this.editor.fireEvent('fullscreenchanged', fullscreen);
            this.triggerLayout();
          }
        }
      },
      _updateFullScreen: function () {
        if (this._fullscreen) {
          var vpRect = uiUtils.getViewportRect();
          this.getDom().style.cssText =
            'border:0;position:fixed;left:0;top:var(--ueditor-top-offset,' +
            (this.editor.options.topOffset || 0) +
            'px);width:' +
            vpRect.width +
            'px;height:' +
            vpRect.height +
            'px;z-index:' +
            (this.getDom().style.zIndex * 1 + 100);
          uiUtils.setViewportOffset(this.getDom(), { left: 0 });
          this.editor.setHeight(
            vpRect.height -
              this.getDom('toolbarbox').offsetHeight -
              this.getDom('bottombar').offsetHeight -
              (this.editor.options.topOffset || 0),
            true,
          );
          if (browser.gecko) {
            try {
              window.onresize();
            } catch (e) {}
          }
        }
      },
      _updateElementPath: function () {
        var bottom = this.getDom('elementpath'),
          list;
        if (this.elementPathEnabled && (list = this.editor.queryCommandValue('elementpath'))) {
          var buff = [];
          for (var i = 0, ci; (ci = list[i]); i++) {
            buff[i] = this.formatHtml(
              '<span unselectable="on" onclick="$$.editor.execCommand(&quot;elementpath&quot;, &quot;' +
                i +
                '&quot;);">' +
                ci +
                '</span>',
            );
          }
          bottom.innerHTML =
            '<div class="edui-editor-breadcrumb" onmousedown="return false;">' +
            this.editor.getLang('elementPathTip') +
            ': ' +
            buff.join(' &gt; ') +
            '</div>';
        } else {
          bottom.style.display = 'none';
        }
      },
      disableElementPath: function () {
        var bottom = this.getDom('elementpath');
        bottom.innerHTML = '';
        bottom.style.display = 'none';
        this.elementPathEnabled = false;
      },
      enableElementPath: function () {
        var bottom = this.getDom('elementpath');
        bottom.style.display = '';
        this.elementPathEnabled = true;
        this._updateElementPath();
      },
      _scale: function () {
        var doc = document,
          editor = this.editor,
          editorHolder = editor.container,
          editorDocument = editor.document,
          toolbarBox = this.getDom('toolbarbox'),
          bottombar = this.getDom('bottombar'),
          scale = this.getDom('scale'),
          scalelayer = this.getDom('scalelayer');
        var isMouseMove = false,
          position = null,
          minEditorHeight = 0,
          minEditorWidth = editor.options.minFrameWidth,
          pageX = 0,
          pageY = 0,
          scaleWidth = 0,
          scaleHeight = 0;
        function down() {
          position = domUtils.getXY(editorHolder);
          if (!minEditorHeight) {
            minEditorHeight = editor.options.minFrameHeight + toolbarBox.offsetHeight + bottombar.offsetHeight;
          }
          scalelayer.style.cssText =
            'position:absolute;left:0;display:;top:0;background-color:#41ABFF;opacity:0.4;filter: Alpha(opacity=40);width:' +
            editorHolder.offsetWidth +
            'px;height:' +
            editorHolder.offsetHeight +
            'px;z-index:' +
            (editor.options.zIndex + 1);
          domUtils.on(doc, 'mousemove', move);
          domUtils.on(editorDocument, 'mouseup', up);
          domUtils.on(doc, 'mouseup', up);
        }
        var me = this;
        this.editor.addListener('fullscreenchanged', function (e, fullScreen) {
          if (fullScreen) {
            me.disableScale();
          } else {
            if (me.editor.options.scaleEnabled) {
              me.enableScale();
              var tmpNode = me.editor.document.createElement('span');
              me.editor.body.appendChild(tmpNode);
              me.editor.body.style.height =
                Math.max(domUtils.getXY(tmpNode).y, me.editor.iframe.offsetHeight - 20) + 'px';
              domUtils.remove(tmpNode);
            }
          }
        });
        function move(event) {
          clearSelection();
          var e = event || window.event;
          pageX = e.pageX || doc.documentElement.scrollLeft + e.clientX;
          pageY = e.pageY || doc.documentElement.scrollTop + e.clientY;
          scaleWidth = pageX - position.x;
          scaleHeight = pageY - position.y;
          if (scaleWidth >= minEditorWidth) {
            isMouseMove = true;
            scalelayer.style.width = scaleWidth + 'px';
          }
          if (scaleHeight >= minEditorHeight) {
            isMouseMove = true;
            scalelayer.style.height = scaleHeight + 'px';
          }
        }
        function up() {
          if (isMouseMove) {
            isMouseMove = false;
            editor.ui._actualFrameWidth = scalelayer.offsetWidth - 2;
            editorHolder.style.width = editor.ui._actualFrameWidth + 'px';
            editor.setHeight(scalelayer.offsetHeight - bottombar.offsetHeight - toolbarBox.offsetHeight - 2, true);
          }
          if (scalelayer) {
            scalelayer.style.display = 'none';
          }
          clearSelection();
          domUtils.un(doc, 'mousemove', move);
          domUtils.un(editorDocument, 'mouseup', up);
          domUtils.un(doc, 'mouseup', up);
        }
        function clearSelection() {
          if (browser.ie) doc.selection.clear();
          else window.getSelection().removeAllRanges();
        }
        this.enableScale = function () {
          if (editor.queryCommandState('source') == 1) return;
          scale.style.display = '';
          this.scaleEnabled = true;
          domUtils.on(scale, 'mousedown', down);
        };
        this.disableScale = function () {
          scale.style.display = 'none';
          this.scaleEnabled = false;
          domUtils.un(scale, 'mousedown', down);
        };
      },
      isFullScreen: function () {
        return this._fullscreen;
      },
      postRender: function () {
        UIBase.prototype.postRender.call(this);
        for (var i = 0; i < this.toolbars.length; i++) {
          this.toolbars[i].postRender();
        }
        var me = this;
        var timerId,
          domUtils = baidu.editor.dom.domUtils,
          updateFullScreenTime = function () {
            clearTimeout(timerId);
            timerId = setTimeout(function () {
              me._updateFullScreen();
            });
          };
        domUtils.on(window, 'resize', updateFullScreenTime);
        me.addListener('destroy', function () {
          domUtils.un(window, 'resize', updateFullScreenTime);
          clearTimeout(timerId);
        });
      },
      showToolbarMsg: function (msg, flag) {
        this.getDom('toolbarmsg_label').innerHTML = msg;
        this.getDom('toolbarmsg').style.display = '';
        if (!flag) {
          var w = this.getDom('upload_dialog');
          w.style.display = 'none';
        }
      },
      hideToolbarMsg: function () {
        this.getDom('toolbarmsg').style.display = 'none';
      },
      mapUrl: function (url) {
        return url ? url.replace('~/', this.editor.options.UEDITOR_CORS_URL || '') : '';
      },
      triggerLayout: function () {
        var dom = this.getDom();
        if (dom.style.zoom == '1') {
          dom.style.zoom = '100%';
        } else {
          dom.style.zoom = '1';
        }
      },
    };
    utils.inherits(EditorUI, baidu.editor.ui.UIBase);
    var instances = {};
    UE.ui.Editor = function (options) {
      var editor = new UE.Editor(options);
      editor.options.editor = editor;
      utils.loadFile(document, {
        href: editor.options.themePath + editor.options.theme + '/css/ueditor.css?dfa5e8ae',
        tag: 'link',
        type: 'text/css',
        rel: 'stylesheet',
      });
      var oldRender = editor.render;
      editor.render = function (holder) {
        if (holder.constructor === String) {
          editor.key = holder;
          instances[holder] = editor;
        }
        utils.domReady(function () {
          editor.langIsReady ? renderUI() : editor.addListener('langReady', renderUI);
          function renderUI() {
            editor.setOpt({ labelMap: editor.options.labelMap || editor.getLang('labelMap') });
            new EditorUI(editor.options);
            if (holder) {
              if (holder.constructor === String) {
                holder = document.getElementById(holder);
              }
              holder && holder.getAttribute('name') && (editor.options.textarea = holder.getAttribute('name'));
              if (holder && /script|textarea/gi.test(holder.tagName)) {
                var newDiv = document.createElement('div');
                holder.parentNode.insertBefore(newDiv, holder);
                var cont = holder.value || holder.innerHTML;
                editor.options.initialContent = /^[\t\r\n ]*$/.test(cont)
                  ? editor.options.initialContent
                  : cont
                      .replace(/>[\n\r\t]+([ ]{4})+/g, '>')
                      .replace(/[\n\r\t]+([ ]{4})+</g, '<')
                      .replace(/>[\n\r\t]+</g, '><');
                holder.className && (newDiv.className = holder.className);
                holder.style.cssText && (newDiv.style.cssText = holder.style.cssText);
                if (/textarea/i.test(holder.tagName)) {
                  editor.textarea = holder;
                  editor.textarea.style.display = 'none';
                } else {
                  holder.parentNode.removeChild(holder);
                }
                if (holder.id) {
                  newDiv.id = holder.id;
                  domUtils.removeAttributes(holder, 'id');
                }
                holder = newDiv;
                holder.innerHTML = '';
              }
            }
            domUtils.addClass(holder, 'edui-' + editor.options.theme);
            editor.ui.render(holder);
            var opt = editor.options;
            editor.container = editor.ui.getDom();
            var parents = domUtils.findParents(holder, true);
            var displays = [];
            for (var i = 0, ci; (ci = parents[i]); i++) {
              displays[i] = ci.style.display;
              ci.style.display = 'block';
            }
            if (opt.initialFrameWidth) {
              opt.minFrameWidth = opt.initialFrameWidth;
            } else {
              opt.minFrameWidth = opt.initialFrameWidth = holder.offsetWidth;
              var styleWidth = holder.style.width;
              if (/%$/.test(styleWidth)) {
                opt.initialFrameWidth = styleWidth;
              }
            }
            if (opt.initialFrameHeight) {
              opt.minFrameHeight = opt.initialFrameHeight;
            } else {
              opt.initialFrameHeight = opt.minFrameHeight = holder.offsetHeight;
            }
            for (var i = 0, ci; (ci = parents[i]); i++) {
              ci.style.display = displays[i];
            }
            if (holder.style.height) {
              holder.style.height = '';
            }
            editor.container.style.width = opt.initialFrameWidth + (/%$/.test(opt.initialFrameWidth) ? '' : 'px');
            editor.container.style.zIndex = opt.zIndex;
            oldRender.call(editor, editor.ui.getDom('iframeholder'));
            editor.fireEvent('afteruiready');
          }
        });
      };
      return editor;
    };
    UE.getEditor = function (id, opt) {
      var editor = instances[id];
      if (!editor) {
        editor = instances[id] = new UE.ui.Editor(opt);
        editor.render(id);
      }
      return editor;
    };
    UE.delEditor = function (id) {
      var editor;
      if ((editor = instances[id])) {
        editor.key && editor.destroy();
        delete instances[id];
      }
    };
    UE.registerUI = function (uiName, fn, index, editorId) {
      utils.each(uiName.split(/\s+/), function (name) {
        baidu.editor.ui[name] = { id: editorId, execFn: fn, index: index };
      });
    };
  })();
  UE.registerUI('xiumi', function (editor, uiName) {
    console.log('启动');
    var btn = new UE.ui.Button({
      name: 'xiumi-connect',
      title: '秀米',
      onclick: function () {
        var dialog = new UE.ui.Dialog({
          iframeUrl: '/static/UEditorPlus/dist-min/dialogs/xiumi/xiumi-ue-dialog-v5.html',
          editor: editor,
          name: 'xiumi-connect',
          title: '秀米图文消息助手',
          cssRules: 'width: ' + (window.innerWidth - 60) + 'px;' + 'height: ' + (window.innerHeight - 60) + 'px;',
        });
        dialog.render();
        dialog.open();
      },
    });
    return btn;
  });
  UE.registerUI('message', function (editor) {
    var editorui = baidu.editor.ui;
    var Message = editorui.Message;
    var holder;
    var _messageItems = [];
    var me = editor;
    me.setOpt('enableMessageShow', true);
    if (me.getOpt('enableMessageShow') === false) {
      return;
    }
    me.addListener('ready', function () {
      holder = document.getElementById(me.ui.id + '_message_holder');
      updateHolderPos();
      setTimeout(function () {
        updateHolderPos();
      }, 500);
    });
    me.addListener('showmessage', function (type, opt) {
      opt = utils.isString(opt) ? { content: opt } : opt;
      var message = new Message({
          timeout: opt.timeout,
          type: opt.type,
          content: opt.content,
          keepshow: opt.keepshow,
          editor: me,
        }),
        mid = opt.id || 'msg_' + (+new Date()).toString(36);
      message.render(holder);
      _messageItems[mid] = message;
      message.reset(opt);
      updateHolderPos();
      return mid;
    });
    me.addListener('updatemessage', function (type, id, opt) {
      opt = utils.isString(opt) ? { content: opt } : opt;
      var message = _messageItems[id];
      message.render(holder);
      message && message.reset(opt);
    });
    me.addListener('hidemessage', function (type, id) {
      var message = _messageItems[id];
      message && message.hide();
    });
    function updateHolderPos() {
      if (!holder || !me.ui) return;
      var toolbarbox = me.ui.getDom('toolbarbox');
      if (toolbarbox) {
        holder.style.top = toolbarbox.offsetHeight + 3 + 'px';
      }
      holder.style.zIndex = Math.max(me.options.zIndex, me.iframe.style.zIndex) + 1;
    }
  });
})();
